/mandos/release

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

« back to all changes in this revision

Viewing changes to mandos-ctl

  • Committer: Teddy Hogeborn
  • Date: 2019-03-30 17:02:33 UTC
  • mto: This revision was merged to the branch mainline in revision 382.
  • Revision ID: teddy@recompile.se-20190330170233-nxu3cgb98q2g3o5j
Fix typo in intro(8mandos).

* intro.xml (INTRODUCTION): Add missing period at end of last sentence
                            of penultimate paragraph.

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
import io
46
46
import tempfile
47
47
import contextlib
 
48
import abc
48
49
 
49
50
import dbus as dbus_python
50
51
 
121
122
                        help="Select all clients")
122
123
    parser.add_argument("-v", "--verbose", action="store_true",
123
124
                        help="Print all fields")
124
 
    parser.add_argument("-j", "--dump-json", dest="commands",
125
 
                        action="append_const", default=[],
126
 
                        const=command.DumpJSON(),
 
125
    parser.add_argument("-j", "--dump-json", action="store_true",
127
126
                        help="Dump client data in JSON format")
128
127
    enable_disable = parser.add_mutually_exclusive_group()
129
 
    enable_disable.add_argument("-e", "--enable", dest="commands",
130
 
                                action="append_const", default=[],
131
 
                                const=command.Enable(),
 
128
    enable_disable.add_argument("-e", "--enable", action="store_true",
132
129
                                help="Enable client")
133
 
    enable_disable.add_argument("-d", "--disable", dest="commands",
134
 
                                action="append_const", default=[],
135
 
                                const=command.Disable(),
 
130
    enable_disable.add_argument("-d", "--disable",
 
131
                                action="store_true",
136
132
                                help="disable client")
137
 
    parser.add_argument("-b", "--bump-timeout", dest="commands",
138
 
                        action="append_const", default=[],
139
 
                        const=command.BumpTimeout(),
 
133
    parser.add_argument("-b", "--bump-timeout", action="store_true",
140
134
                        help="Bump timeout for client")
141
135
    start_stop_checker = parser.add_mutually_exclusive_group()
142
136
    start_stop_checker.add_argument("--start-checker",
143
 
                                    dest="commands",
144
 
                                    action="append_const", default=[],
145
 
                                    const=command.StartChecker(),
 
137
                                    action="store_true",
146
138
                                    help="Start checker for client")
147
 
    start_stop_checker.add_argument("--stop-checker", dest="commands",
148
 
                                    action="append_const", default=[],
149
 
                                    const=command.StopChecker(),
 
139
    start_stop_checker.add_argument("--stop-checker",
 
140
                                    action="store_true",
150
141
                                    help="Stop checker for client")
151
 
    parser.add_argument("-V", "--is-enabled", dest="commands",
152
 
                        action="append_const", default=[],
153
 
                        const=command.IsEnabled(),
 
142
    parser.add_argument("-V", "--is-enabled", action="store_true",
154
143
                        help="Check if client is enabled")
155
 
    parser.add_argument("-r", "--remove", dest="commands",
156
 
                        action="append_const", default=[],
157
 
                        const=command.Remove(),
 
144
    parser.add_argument("-r", "--remove", action="store_true",
158
145
                        help="Remove client")
159
 
    parser.add_argument("-c", "--checker", dest="commands",
160
 
                        action="append", default=[],
161
 
                        metavar="COMMAND", type=command.SetChecker,
 
146
    parser.add_argument("-c", "--checker",
162
147
                        help="Set checker command for client")
163
 
    parser.add_argument(
164
 
        "-t", "--timeout", dest="commands", action="append",
165
 
        default=[], metavar="TIME",
166
 
        type=command.SetTimeout.argparse(string_to_delta),
167
 
        help="Set timeout for client")
168
 
    parser.add_argument(
169
 
        "--extended-timeout", dest="commands", action="append",
170
 
        default=[], metavar="TIME",
171
 
        type=command.SetExtendedTimeout.argparse(string_to_delta),
172
 
        help="Set extended timeout for client")
173
 
    parser.add_argument(
174
 
        "-i", "--interval", dest="commands", action="append",
175
 
        default=[], metavar="TIME",
176
 
        type=command.SetInterval.argparse(string_to_delta),
177
 
        help="Set checker interval for client")
 
148
    parser.add_argument("-t", "--timeout", type=string_to_delta,
 
149
                        help="Set timeout for client")
 
150
    parser.add_argument("--extended-timeout", type=string_to_delta,
 
151
                        help="Set extended timeout for client")
 
152
    parser.add_argument("-i", "--interval", type=string_to_delta,
 
153
                        help="Set checker interval for client")
178
154
    approve_deny_default = parser.add_mutually_exclusive_group()
179
155
    approve_deny_default.add_argument(
180
 
        "--approve-by-default", dest="commands",
181
 
        action="append_const", default=[],
182
 
        const=command.ApproveByDefault(),
 
156
        "--approve-by-default", action="store_true",
 
157
        default=None, dest="approved_by_default",
183
158
        help="Set client to be approved by default")
184
159
    approve_deny_default.add_argument(
185
 
        "--deny-by-default", dest="commands",
186
 
        action="append_const", default=[],
187
 
        const=command.DenyByDefault(),
 
160
        "--deny-by-default", action="store_false",
 
161
        dest="approved_by_default",
188
162
        help="Set client to be denied by default")
189
 
    parser.add_argument(
190
 
        "--approval-delay", dest="commands", action="append",
191
 
        default=[], metavar="TIME",
192
 
        type=command.SetApprovalDelay.argparse(string_to_delta),
193
 
        help="Set delay before client approve/deny")
194
 
    parser.add_argument(
195
 
        "--approval-duration", dest="commands", action="append",
196
 
        default=[], metavar="TIME",
197
 
        type=command.SetApprovalDuration.argparse(string_to_delta),
198
 
        help="Set duration of one client approval")
199
 
    parser.add_argument("-H", "--host", dest="commands",
200
 
                        action="append", default=[], metavar="STRING",
201
 
                        type=command.SetHost,
202
 
                        help="Set host for client")
203
 
    parser.add_argument(
204
 
        "-s", "--secret", dest="commands", action="append",
205
 
        default=[], metavar="FILENAME",
206
 
        type=command.SetSecret.argparse(argparse.FileType(mode="rb")),
207
 
        help="Set password blob (file) for client")
 
163
    parser.add_argument("--approval-delay", type=string_to_delta,
 
164
                        help="Set delay before client approve/deny")
 
165
    parser.add_argument("--approval-duration", type=string_to_delta,
 
166
                        help="Set duration of one client approval")
 
167
    parser.add_argument("-H", "--host", help="Set host for client")
 
168
    parser.add_argument("-s", "--secret",
 
169
                        type=argparse.FileType(mode="rb"),
 
170
                        help="Set password blob (file) for client")
208
171
    approve_deny = parser.add_mutually_exclusive_group()
209
172
    approve_deny.add_argument(
210
 
        "-A", "--approve", dest="commands", action="append_const",
211
 
        default=[], const=command.Approve(),
 
173
        "-A", "--approve", action="store_true",
212
174
        help="Approve any current client request")
213
 
    approve_deny.add_argument("-D", "--deny", dest="commands",
214
 
                              action="append_const", default=[],
215
 
                              const=command.Deny(),
 
175
    approve_deny.add_argument("-D", "--deny", action="store_true",
216
176
                              help="Deny any current client request")
217
177
    parser.add_argument("--debug", action="store_true",
218
178
                        help="Debug mode (show D-Bus commands)")
409
369
    """Apply additional restrictions on options, not expressible in
410
370
argparse"""
411
371
 
412
 
    def has_commands(options, commands=None):
413
 
        if commands is None:
414
 
            commands = (command.Enable,
415
 
                        command.Disable,
416
 
                        command.BumpTimeout,
417
 
                        command.StartChecker,
418
 
                        command.StopChecker,
419
 
                        command.IsEnabled,
420
 
                        command.Remove,
421
 
                        command.SetChecker,
422
 
                        command.SetTimeout,
423
 
                        command.SetExtendedTimeout,
424
 
                        command.SetInterval,
425
 
                        command.ApproveByDefault,
426
 
                        command.DenyByDefault,
427
 
                        command.SetApprovalDelay,
428
 
                        command.SetApprovalDuration,
429
 
                        command.SetHost,
430
 
                        command.SetSecret,
431
 
                        command.Approve,
432
 
                        command.Deny)
433
 
        return any(isinstance(cmd, commands)
434
 
                   for cmd in options.commands)
 
372
    def has_actions(options):
 
373
        return any((options.enable,
 
374
                    options.disable,
 
375
                    options.bump_timeout,
 
376
                    options.start_checker,
 
377
                    options.stop_checker,
 
378
                    options.is_enabled,
 
379
                    options.remove,
 
380
                    options.checker is not None,
 
381
                    options.timeout is not None,
 
382
                    options.extended_timeout is not None,
 
383
                    options.interval is not None,
 
384
                    options.approved_by_default is not None,
 
385
                    options.approval_delay is not None,
 
386
                    options.approval_duration is not None,
 
387
                    options.host is not None,
 
388
                    options.secret is not None,
 
389
                    options.approve,
 
390
                    options.deny))
435
391
 
436
 
    if has_commands(options) and not (options.client or options.all):
 
392
    if has_actions(options) and not (options.client or options.all):
437
393
        parser.error("Options require clients names or --all.")
438
 
    if options.verbose and has_commands(options):
 
394
    if options.verbose and has_actions(options):
439
395
        parser.error("--verbose can only be used alone.")
440
 
    if (has_commands(options, (command.DumpJSON,))
441
 
        and (options.verbose or len(options.commands) > 1)):
 
396
    if options.dump_json and (options.verbose
 
397
                              or has_actions(options)):
442
398
        parser.error("--dump-json can only be used alone.")
443
 
    if options.all and not has_commands(options):
 
399
    if options.all and not has_actions(options):
444
400
        parser.error("--all requires an action.")
445
 
    if (has_commands(options, (command.IsEnabled,))
446
 
        and len(options.client) > 1):
 
401
    if options.is_enabled and len(options.client) > 1:
447
402
        parser.error("--is-enabled requires exactly one client")
448
 
    if (len(options.commands) > 1
449
 
        and has_commands(options, (command.Remove,))
450
 
        and not has_commands(options, (command.Deny,))):
451
 
        parser.error("--remove can only be combined with --deny")
 
403
    if options.remove:
 
404
        options.remove = False
 
405
        if has_actions(options) and not options.deny:
 
406
            parser.error("--remove can only be combined with --deny")
 
407
        options.remove = True
 
408
 
452
409
 
453
410
 
454
411
class dbus(object):
594
551
 
595
552
def commands_from_options(options):
596
553
 
597
 
    commands = list(options.commands)
598
 
 
599
 
    def find_cmd(cmd, commands):
600
 
        i = 0
601
 
        for i, c in enumerate(commands):
602
 
            if isinstance(c, cmd):
603
 
                return i
604
 
        return i+1
605
 
 
606
 
    # If command.Remove is present, move any instances of command.Deny
607
 
    # to occur ahead of command.Remove.
608
 
    index_of_remove = find_cmd(command.Remove, commands)
609
 
    before_remove = commands[:index_of_remove]
610
 
    after_remove = commands[index_of_remove:]
611
 
    cleaned_after = []
612
 
    for cmd in after_remove:
613
 
        if isinstance(cmd, command.Deny):
614
 
            before_remove.append(cmd)
 
554
    commands = []
 
555
 
 
556
    if options.is_enabled:
 
557
        commands.append(command.IsEnabled())
 
558
 
 
559
    if options.approve:
 
560
        commands.append(command.Approve())
 
561
 
 
562
    if options.deny:
 
563
        commands.append(command.Deny())
 
564
 
 
565
    if options.remove:
 
566
        commands.append(command.Remove())
 
567
 
 
568
    if options.dump_json:
 
569
        commands.append(command.DumpJSON())
 
570
 
 
571
    if options.enable:
 
572
        commands.append(command.Enable())
 
573
 
 
574
    if options.disable:
 
575
        commands.append(command.Disable())
 
576
 
 
577
    if options.bump_timeout:
 
578
        commands.append(command.BumpTimeout())
 
579
 
 
580
    if options.start_checker:
 
581
        commands.append(command.StartChecker())
 
582
 
 
583
    if options.stop_checker:
 
584
        commands.append(command.StopChecker())
 
585
 
 
586
    if options.approved_by_default is not None:
 
587
        if options.approved_by_default:
 
588
            commands.append(command.ApproveByDefault())
615
589
        else:
616
 
            cleaned_after.append(cmd)
617
 
    if cleaned_after != after_remove:
618
 
        commands = before_remove + cleaned_after
 
590
            commands.append(command.DenyByDefault())
 
591
 
 
592
    if options.checker is not None:
 
593
        commands.append(command.SetChecker(options.checker))
 
594
 
 
595
    if options.host is not None:
 
596
        commands.append(command.SetHost(options.host))
 
597
 
 
598
    if options.secret is not None:
 
599
        commands.append(command.SetSecret(options.secret))
 
600
 
 
601
    if options.timeout is not None:
 
602
        commands.append(command.SetTimeout(options.timeout))
 
603
 
 
604
    if options.extended_timeout:
 
605
        commands.append(
 
606
            command.SetExtendedTimeout(options.extended_timeout))
 
607
 
 
608
    if options.interval is not None:
 
609
        commands.append(command.SetInterval(options.interval))
 
610
 
 
611
    if options.approval_delay is not None:
 
612
        commands.append(
 
613
            command.SetApprovalDelay(options.approval_delay))
 
614
 
 
615
    if options.approval_duration is not None:
 
616
        commands.append(
 
617
            command.SetApprovalDuration(options.approval_duration))
619
618
 
620
619
    # If no command option has been given, show table of clients,
621
620
    # optionally verbosely
836
835
        def __init__(self, value):
837
836
            self.value_to_set = value
838
837
 
839
 
        @classmethod
840
 
        def argparse(cls, argtype):
841
 
            def cmdtype(arg):
842
 
                return cls(argtype(arg))
843
 
            return cmdtype
844
838
 
845
839
    class SetChecker(PropertySetterValue):
846
840
        propname = "Checker"
972
966
 
973
967
    def test_actions_requires_client_or_all(self):
974
968
        for action, value in self.actions.items():
975
 
            args = self.actionargs(action, value)
 
969
            options = self.parser.parse_args()
 
970
            setattr(options, action, value)
976
971
            with self.assertParseError():
977
 
                self.parse_args(args)
 
972
                self.check_option_syntax(options)
978
973
 
979
 
    # This mostly corresponds to the definition from has_commands() in
 
974
    # This mostly corresponds to the definition from has_actions() in
980
975
    # check_option_syntax()
981
976
    actions = {
982
 
        "--enable": None,
983
 
        "--disable": None,
984
 
        "--bump-timeout": None,
985
 
        "--start-checker": None,
986
 
        "--stop-checker": None,
987
 
        "--is-enabled": None,
988
 
        "--remove": None,
989
 
        "--checker": "x",
990
 
        "--timeout": "PT0S",
991
 
        "--extended-timeout": "PT0S",
992
 
        "--interval": "PT0S",
993
 
        "--approve-by-default": None,
994
 
        "--deny-by-default": None,
995
 
        "--approval-delay": "PT0S",
996
 
        "--approval-duration": "PT0S",
997
 
        "--host": "hostname",
998
 
        "--secret": "/dev/null",
999
 
        "--approve": None,
1000
 
        "--deny": None,
 
977
        # The actual values set here are not that important, but we do
 
978
        # at least stick to the correct types, even though they are
 
979
        # never used
 
980
        "enable": True,
 
981
        "disable": True,
 
982
        "bump_timeout": True,
 
983
        "start_checker": True,
 
984
        "stop_checker": True,
 
985
        "is_enabled": True,
 
986
        "remove": True,
 
987
        "checker": "x",
 
988
        "timeout": datetime.timedelta(),
 
989
        "extended_timeout": datetime.timedelta(),
 
990
        "interval": datetime.timedelta(),
 
991
        "approved_by_default": True,
 
992
        "approval_delay": datetime.timedelta(),
 
993
        "approval_duration": datetime.timedelta(),
 
994
        "host": "x",
 
995
        "secret": io.BytesIO(b"x"),
 
996
        "approve": True,
 
997
        "deny": True,
1001
998
    }
1002
999
 
1003
 
    @staticmethod
1004
 
    def actionargs(action, value, *args):
1005
 
        if value is not None:
1006
 
            return [action, value] + list(args)
1007
 
        else:
1008
 
            return [action] + list(args)
1009
 
 
1010
1000
    @contextlib.contextmanager
1011
1001
    def assertParseError(self):
1012
1002
        with self.assertRaises(SystemExit) as e:
1017
1007
        # /argparse.html#exiting-methods
1018
1008
        self.assertEqual(2, e.exception.code)
1019
1009
 
1020
 
    def parse_args(self, args):
1021
 
        options = self.parser.parse_args(args)
1022
 
        check_option_syntax(self.parser, options)
1023
 
 
1024
1010
    @staticmethod
1025
1011
    @contextlib.contextmanager
1026
1012
    def redirect_stderr_to_devnull():
1037
1023
 
1038
1024
    def test_actions_all_conflicts_with_verbose(self):
1039
1025
        for action, value in self.actions.items():
1040
 
            args = self.actionargs(action, value, "--all",
1041
 
                                   "--verbose")
 
1026
            options = self.parser.parse_args()
 
1027
            setattr(options, action, value)
 
1028
            options.all = True
 
1029
            options.verbose = True
1042
1030
            with self.assertParseError():
1043
 
                self.parse_args(args)
 
1031
                self.check_option_syntax(options)
1044
1032
 
1045
1033
    def test_actions_with_client_conflicts_with_verbose(self):
1046
1034
        for action, value in self.actions.items():
1047
 
            args = self.actionargs(action, value, "--verbose",
1048
 
                                   "client")
 
1035
            options = self.parser.parse_args()
 
1036
            setattr(options, action, value)
 
1037
            options.verbose = True
 
1038
            options.client = ["client"]
1049
1039
            with self.assertParseError():
1050
 
                self.parse_args(args)
 
1040
                self.check_option_syntax(options)
1051
1041
 
1052
1042
    def test_dump_json_conflicts_with_verbose(self):
1053
 
        args = ["--dump-json", "--verbose"]
 
1043
        options = self.parser.parse_args()
 
1044
        options.dump_json = True
 
1045
        options.verbose = True
1054
1046
        with self.assertParseError():
1055
 
            self.parse_args(args)
 
1047
            self.check_option_syntax(options)
1056
1048
 
1057
1049
    def test_dump_json_conflicts_with_action(self):
1058
1050
        for action, value in self.actions.items():
1059
 
            args = self.actionargs(action, value, "--dump-json")
 
1051
            options = self.parser.parse_args()
 
1052
            setattr(options, action, value)
 
1053
            options.dump_json = True
1060
1054
            with self.assertParseError():
1061
 
                self.parse_args(args)
 
1055
                self.check_option_syntax(options)
1062
1056
 
1063
1057
    def test_all_can_not_be_alone(self):
1064
 
        args = ["--all"]
 
1058
        options = self.parser.parse_args()
 
1059
        options.all = True
1065
1060
        with self.assertParseError():
1066
 
            self.parse_args(args)
 
1061
            self.check_option_syntax(options)
1067
1062
 
1068
1063
    def test_all_is_ok_with_any_action(self):
1069
1064
        for action, value in self.actions.items():
1070
 
            args = self.actionargs(action, value, "--all")
1071
 
            self.parse_args(args)
 
1065
            options = self.parser.parse_args()
 
1066
            setattr(options, action, value)
 
1067
            options.all = True
 
1068
            self.check_option_syntax(options)
1072
1069
 
1073
1070
    def test_any_action_is_ok_with_one_client(self):
1074
1071
        for action, value in self.actions.items():
1075
 
            args = self.actionargs(action, value, "client")
1076
 
            self.parse_args(args)
 
1072
            options = self.parser.parse_args()
 
1073
            setattr(options, action, value)
 
1074
            options.client = ["client"]
 
1075
            self.check_option_syntax(options)
1077
1076
 
1078
1077
    def test_one_client_with_all_actions_except_is_enabled(self):
 
1078
        options = self.parser.parse_args()
1079
1079
        for action, value in self.actions.items():
1080
 
            if action == "--is-enabled":
 
1080
            if action == "is_enabled":
1081
1081
                continue
1082
 
            args = self.actionargs(action, value, "client")
1083
 
            self.parse_args(args)
 
1082
            setattr(options, action, value)
 
1083
        options.client = ["client"]
 
1084
        self.check_option_syntax(options)
1084
1085
 
1085
1086
    def test_two_clients_with_all_actions_except_is_enabled(self):
 
1087
        options = self.parser.parse_args()
1086
1088
        for action, value in self.actions.items():
1087
 
            if action == "--is-enabled":
 
1089
            if action == "is_enabled":
1088
1090
                continue
1089
 
            args = self.actionargs(action, value, "client1",
1090
 
                                   "client2")
1091
 
            self.parse_args(args)
 
1091
            setattr(options, action, value)
 
1092
        options.client = ["client1", "client2"]
 
1093
        self.check_option_syntax(options)
1092
1094
 
1093
1095
    def test_two_clients_are_ok_with_actions_except_is_enabled(self):
1094
1096
        for action, value in self.actions.items():
1095
 
            if action == "--is-enabled":
 
1097
            if action == "is_enabled":
1096
1098
                continue
1097
 
            args = self.actionargs(action, value, "client1",
1098
 
                                   "client2")
1099
 
            self.parse_args(args)
 
1099
            options = self.parser.parse_args()
 
1100
            setattr(options, action, value)
 
1101
            options.client = ["client1", "client2"]
 
1102
            self.check_option_syntax(options)
1100
1103
 
1101
1104
    def test_is_enabled_fails_without_client(self):
1102
 
        args = ["--is-enabled"]
 
1105
        options = self.parser.parse_args()
 
1106
        options.is_enabled = True
1103
1107
        with self.assertParseError():
1104
 
            self.parse_args(args)
 
1108
            self.check_option_syntax(options)
1105
1109
 
1106
1110
    def test_is_enabled_fails_with_two_clients(self):
1107
 
        args = ["--is-enabled", "client1", "client2"]
 
1111
        options = self.parser.parse_args()
 
1112
        options.is_enabled = True
 
1113
        options.client = ["client1", "client2"]
1108
1114
        with self.assertParseError():
1109
 
            self.parse_args(args)
 
1115
            self.check_option_syntax(options)
1110
1116
 
1111
1117
    def test_remove_can_only_be_combined_with_action_deny(self):
1112
1118
        for action, value in self.actions.items():
1113
 
            if action in {"--remove", "--deny"}:
 
1119
            if action in {"remove", "deny"}:
1114
1120
                continue
1115
 
            args = self.actionargs(action, value, "--all",
1116
 
                                   "--remove")
 
1121
            options = self.parser.parse_args()
 
1122
            setattr(options, action, value)
 
1123
            options.all = True
 
1124
            options.remove = True
1117
1125
            with self.assertParseError():
1118
 
                self.parse_args(args)
 
1126
                self.check_option_syntax(options)
1119
1127
 
1120
1128
 
1121
1129
class Test_dbus_exceptions(unittest.TestCase):
2062
2070
    def runTest(self):
2063
2071
        if not hasattr(self, "command"):
2064
2072
            return              # Abstract TestCase class
2065
 
 
2066
 
        if hasattr(self, "values_to_set"):
2067
 
            cmd_args = [(value,) for value in self.values_to_set]
2068
 
            values_to_get = getattr(self, "values_to_get",
2069
 
                                    self.values_to_set)
2070
 
        else:
2071
 
            cmd_args = [() for x in range(len(self.values_to_get))]
2072
 
            values_to_get = self.values_to_get
2073
 
        for value_to_get, cmd_arg in zip(values_to_get, cmd_args):
2074
 
            for clientpath in self.bus.clients:
2075
 
                self.bus.clients[clientpath][self.propname] = (
2076
 
                    Unique())
2077
 
            self.command(*cmd_arg).run(self.bus.clients, self.bus)
2078
 
            for clientpath in self.bus.clients:
2079
 
                value = (self.bus.clients[clientpath]
2080
 
                         [self.propname])
 
2073
        values_to_get = getattr(self, "values_to_get",
 
2074
                                self.values_to_set)
 
2075
        for value_to_set, value_to_get in zip(self.values_to_set,
 
2076
                                              values_to_get):
 
2077
            for clientpath in self.bus.clients:
 
2078
                self.bus.clients[clientpath][self.propname] = Unique()
 
2079
            self.run_command(value_to_set, self.bus.clients)
 
2080
            for clientpath in self.bus.clients:
 
2081
                value = self.bus.clients[clientpath][self.propname]
2081
2082
                self.assertNotIsInstance(value, Unique)
2082
2083
                self.assertEqual(value_to_get, value)
2083
2084
 
 
2085
    def run_command(self, value, clients):
 
2086
        self.command().run(clients, self.bus)
 
2087
 
2084
2088
 
2085
2089
class TestEnableCmd(TestPropertySetterCmd):
2086
2090
    command = command.Enable
2087
2091
    propname = "Enabled"
2088
 
    values_to_get = [True]
 
2092
    values_to_set = [True]
2089
2093
 
2090
2094
 
2091
2095
class TestDisableCmd(TestPropertySetterCmd):
2092
2096
    command = command.Disable
2093
2097
    propname = "Enabled"
2094
 
    values_to_get = [False]
 
2098
    values_to_set = [False]
2095
2099
 
2096
2100
 
2097
2101
class TestBumpTimeoutCmd(TestPropertySetterCmd):
2098
2102
    command = command.BumpTimeout
2099
2103
    propname = "LastCheckedOK"
2100
 
    values_to_get = [""]
 
2104
    values_to_set = [""]
2101
2105
 
2102
2106
 
2103
2107
class TestStartCheckerCmd(TestPropertySetterCmd):
2104
2108
    command = command.StartChecker
2105
2109
    propname = "CheckerRunning"
2106
 
    values_to_get = [True]
 
2110
    values_to_set = [True]
2107
2111
 
2108
2112
 
2109
2113
class TestStopCheckerCmd(TestPropertySetterCmd):
2110
2114
    command = command.StopChecker
2111
2115
    propname = "CheckerRunning"
2112
 
    values_to_get = [False]
 
2116
    values_to_set = [False]
2113
2117
 
2114
2118
 
2115
2119
class TestApproveByDefaultCmd(TestPropertySetterCmd):
2116
2120
    command = command.ApproveByDefault
2117
2121
    propname = "ApprovedByDefault"
2118
 
    values_to_get = [True]
 
2122
    values_to_set = [True]
2119
2123
 
2120
2124
 
2121
2125
class TestDenyByDefaultCmd(TestPropertySetterCmd):
2122
2126
    command = command.DenyByDefault
2123
2127
    propname = "ApprovedByDefault"
2124
 
    values_to_get = [False]
2125
 
 
2126
 
 
2127
 
class TestSetCheckerCmd(TestPropertySetterCmd):
 
2128
    values_to_set = [False]
 
2129
 
 
2130
 
 
2131
class TestPropertySetterValueCmd(TestPropertySetterCmd):
 
2132
    """Abstract class for tests of PropertySetterValueCmd classes"""
 
2133
 
 
2134
    def run_command(self, value, clients):
 
2135
        self.command(value).run(clients, self.bus)
 
2136
 
 
2137
 
 
2138
class TestSetCheckerCmd(TestPropertySetterValueCmd):
2128
2139
    command = command.SetChecker
2129
2140
    propname = "Checker"
2130
2141
    values_to_set = ["", ":", "fping -q -- %s"]
2131
2142
 
2132
2143
 
2133
 
class TestSetHostCmd(TestPropertySetterCmd):
 
2144
class TestSetHostCmd(TestPropertySetterValueCmd):
2134
2145
    command = command.SetHost
2135
2146
    propname = "Host"
2136
2147
    values_to_set = ["192.0.2.3", "client.example.org"]
2137
2148
 
2138
2149
 
2139
 
class TestSetSecretCmd(TestPropertySetterCmd):
 
2150
class TestSetSecretCmd(TestPropertySetterValueCmd):
2140
2151
    command = command.SetSecret
2141
2152
    propname = "Secret"
2142
2153
    values_to_set = [io.BytesIO(b""),
2144
2155
    values_to_get = [f.getvalue() for f in values_to_set]
2145
2156
 
2146
2157
 
2147
 
class TestSetTimeoutCmd(TestPropertySetterCmd):
 
2158
class TestSetTimeoutCmd(TestPropertySetterValueCmd):
2148
2159
    command = command.SetTimeout
2149
2160
    propname = "Timeout"
2150
2161
    values_to_set = [datetime.timedelta(),
2155
2166
    values_to_get = [dt.total_seconds()*1000 for dt in values_to_set]
2156
2167
 
2157
2168
 
2158
 
class TestSetExtendedTimeoutCmd(TestPropertySetterCmd):
 
2169
class TestSetExtendedTimeoutCmd(TestPropertySetterValueCmd):
2159
2170
    command = command.SetExtendedTimeout
2160
2171
    propname = "ExtendedTimeout"
2161
2172
    values_to_set = [datetime.timedelta(),
2166
2177
    values_to_get = [dt.total_seconds()*1000 for dt in values_to_set]
2167
2178
 
2168
2179
 
2169
 
class TestSetIntervalCmd(TestPropertySetterCmd):
 
2180
class TestSetIntervalCmd(TestPropertySetterValueCmd):
2170
2181
    command = command.SetInterval
2171
2182
    propname = "Interval"
2172
2183
    values_to_set = [datetime.timedelta(),
2177
2188
    values_to_get = [dt.total_seconds()*1000 for dt in values_to_set]
2178
2189
 
2179
2190
 
2180
 
class TestSetApprovalDelayCmd(TestPropertySetterCmd):
 
2191
class TestSetApprovalDelayCmd(TestPropertySetterValueCmd):
2181
2192
    command = command.SetApprovalDelay
2182
2193
    propname = "ApprovalDelay"
2183
2194
    values_to_set = [datetime.timedelta(),
2188
2199
    values_to_get = [dt.total_seconds()*1000 for dt in values_to_set]
2189
2200
 
2190
2201
 
2191
 
class TestSetApprovalDurationCmd(TestPropertySetterCmd):
 
2202
class TestSetApprovalDurationCmd(TestPropertySetterValueCmd):
2192
2203
    command = command.SetApprovalDuration
2193
2204
    propname = "ApprovalDuration"
2194
2205
    values_to_set = [datetime.timedelta(),