File: mock_runner.py

package info (click to toggle)
pcs 0.12.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 16,148 kB
  • sloc: python: 238,810; xml: 20,833; ruby: 13,203; makefile: 1,595; sh: 484
file content (141 lines) | stat: -rw-r--r-- 4,188 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
from pcs import settings

from pcs_test.tools.assertions import assert_xml_equal

CALL_TYPE_RUNNER = "CALL_TYPE_RUNNER"


class CheckStdinEqual:
    def __init__(self, expected_stdin):
        self.expected_stdin = expected_stdin

    def __call__(self, stdin, command, order_num):
        del order_num
        if stdin != self.expected_stdin:
            raise AssertionError(
                (
                    "With command\n\n    '{0}'"
                    "\n\nexpected stdin:\n\n'{1}'"
                    "\n\nbut was:\n\n'{2}'"
                ).format(command, self.expected_stdin, stdin)
            )


class CheckStdinEqualXml:
    def __init__(self, expected_stdin):
        self.expected_stdin = expected_stdin

    def __call__(self, stdin, command, order_num):
        assert_xml_equal(
            self.expected_stdin,
            stdin,
            (
                "Trying to run command no. {0}"
                "\n\n    '{1}'\n\nwith expected xml stdin.\n"
            ).format(order_num, command),
        )


def check_no_stdin(stdin, command, order_num):
    del order_num
    if stdin:
        raise AssertionError(
            (
                "With command\n\n    '{0}'\n\nno stdin expected but was"
                "\n\n'{1}'"
            ).format(command, stdin)
        )


COMMAND_COMPLETIONS = {
    "cibadmin": settings.cibadmin_exec,
    "corosync": settings.corosync_exec,
    "corosync-cfgtool": settings.corosync_cfgtool_exec,
    "corosync-qdevice-net-certutil": settings.corosync_qdevice_net_certutil_exec,
    "corosync-quorumtool": settings.corosync_quorumtool_exec,
    "crm_diff": settings.crm_diff_exec,
    "crm_mon": settings.crm_mon_exec,
    "crm_node": settings.crm_node_exec,
    "crm_resource": settings.crm_resource_exec,
    "crm_rule": settings.crm_rule_exec,
    "crm_simulate": settings.crm_simulate_exec,
    "crm_ticket": settings.crm_ticket_exec,
    "crm_verify": settings.crm_verify_exec,
    "iso8601": settings.iso8601_exec,
    "sbd": settings.sbd_exec,
    "stonith_admin": settings.stonith_admin_exec,
}


def complete_command(command):
    for shortcut, full_path in COMMAND_COMPLETIONS.items():
        if command[0] == shortcut:
            return [full_path] + command[1:]
    return command


def bad_call(order_num, expected_command, entered_command):
    return "As {0}. command expected\n    '{1}'\nbut was\n    '{2}'".format(
        order_num, expected_command, entered_command
    )


class Call:
    type = CALL_TYPE_RUNNER

    def __init__(
        self,
        command,
        stdout="",
        stderr="",
        returncode=0,
        check_stdin=None,
        env=None,
    ):
        """
        callable check_stdin raises AssertionError when given stdin doesn't
            match
        """
        self.type = CALL_TYPE_RUNNER
        self.command = complete_command(command)
        self.stdout = stdout
        self.stderr = stderr
        self.returncode = returncode
        self.check_stdin = check_stdin if check_stdin else check_no_stdin
        self.env = env or {}

    def __repr__(self):
        return str("<Runner '{0}' returncode='{1}' env='{2}'>").format(
            self.command, self.returncode, self.env
        )


class Runner:
    def __init__(self, call_queue=None, env_vars=None):
        self.__call_queue = call_queue
        self.__env_vars = env_vars if env_vars else {}

    @property
    def env_vars(self):
        return self.__env_vars

    def run(
        self, args, stdin_string=None, env_extend=None, binary_output=False
    ):
        del binary_output
        i, call = self.__call_queue.take(CALL_TYPE_RUNNER, args)

        if args != call.command:
            raise self.__call_queue.error_with_context(
                bad_call(i, call.command, args)
            )

        call.check_stdin(stdin_string, args, i)
        env = dict(self.env_vars)
        if env_extend:
            env.update(env_extend)
        if env != call.env:
            raise self.__call_queue.error_with_context(
                f"Command #{i}: ENV doesn't match. Expected: {call.env}; Real: {env}"
            )
        return call.stdout, call.stderr, call.returncode