]>
Commit | Line | Data |
---|---|---|
e306af50 | 1 | # type: ignore |
9f95a23c TL |
2 | import argparse |
3 | import mock | |
4 | import os | |
5 | import sys | |
6 | import unittest | |
7 | ||
8 | import pytest | |
9 | ||
10 | if sys.version_info >= (3, 3): | |
11 | from importlib.machinery import SourceFileLoader | |
12 | cd = SourceFileLoader('cephadm', 'cephadm').load_module() | |
13 | else: | |
14 | import imp | |
15 | cd = imp.load_source('cephadm', 'cephadm') | |
16 | ||
17 | class TestCephAdm(object): | |
18 | def test_is_fsid(self): | |
19 | assert not cd.is_fsid('no-uuid') | |
20 | ||
21 | def test__get_parser_image(self): | |
22 | args = cd._parse_args(['--image', 'foo', 'version']) | |
23 | assert args.image == 'foo' | |
24 | ||
25 | def test_CustomValidation(self): | |
26 | assert cd._parse_args(['deploy', '--name', 'mon.a', '--fsid', 'fsid']) | |
27 | ||
28 | with pytest.raises(SystemExit): | |
29 | cd._parse_args(['deploy', '--name', 'wrong', '--fsid', 'fsid']) | |
30 | ||
31 | @pytest.mark.parametrize("test_input, expected", [ | |
32 | ("podman version 1.6.2", (1,6,2)), | |
33 | ("podman version 1.6.2-stable2", (1,6,2)), | |
34 | ]) | |
35 | def test_parse_podman_version(self, test_input, expected): | |
36 | assert cd._parse_podman_version(test_input) == expected | |
37 | ||
38 | def test_parse_podman_version_invalid(self): | |
39 | with pytest.raises(ValueError) as res: | |
40 | cd._parse_podman_version('podman version inval.id') | |
41 | assert 'inval' in str(res.value) | |
42 | ||
43 | @pytest.mark.parametrize("test_input, expected", [ | |
44 | ( | |
45 | """ | |
46 | default via 192.168.178.1 dev enxd89ef3f34260 proto dhcp metric 100 | |
47 | 10.0.0.0/8 via 10.4.0.1 dev tun0 proto static metric 50 | |
48 | 10.3.0.0/21 via 10.4.0.1 dev tun0 proto static metric 50 | |
49 | 10.4.0.1 dev tun0 proto kernel scope link src 10.4.0.2 metric 50 | |
50 | 137.1.0.0/16 via 10.4.0.1 dev tun0 proto static metric 50 | |
51 | 138.1.0.0/16 via 10.4.0.1 dev tun0 proto static metric 50 | |
52 | 139.1.0.0/16 via 10.4.0.1 dev tun0 proto static metric 50 | |
53 | 140.1.0.0/17 via 10.4.0.1 dev tun0 proto static metric 50 | |
54 | 141.1.0.0/16 via 10.4.0.1 dev tun0 proto static metric 50 | |
55 | 169.254.0.0/16 dev docker0 scope link metric 1000 | |
56 | 172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 | |
57 | 192.168.39.0/24 dev virbr1 proto kernel scope link src 192.168.39.1 linkdown | |
58 | 192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown | |
59 | 192.168.178.0/24 dev enxd89ef3f34260 proto kernel scope link src 192.168.178.28 metric 100 | |
60 | 192.168.178.1 dev enxd89ef3f34260 proto static scope link metric 100 | |
61 | 195.135.221.12 via 192.168.178.1 dev enxd89ef3f34260 proto static metric 100 | |
62 | """, | |
63 | { | |
64 | '10.4.0.1': ['10.4.0.2'], | |
65 | '172.17.0.0/16': ['172.17.0.1'], | |
66 | '192.168.39.0/24': ['192.168.39.1'], | |
67 | '192.168.122.0/24': ['192.168.122.1'], | |
68 | '192.168.178.0/24': ['192.168.178.28'] | |
69 | } | |
70 | ), ( | |
71 | """ | |
72 | default via 10.3.64.1 dev eno1 proto static metric 100 | |
73 | 10.3.64.0/24 dev eno1 proto kernel scope link src 10.3.64.23 metric 100 | |
74 | 10.3.64.0/24 dev eno1 proto kernel scope link src 10.3.64.27 metric 100 | |
75 | 10.88.0.0/16 dev cni-podman0 proto kernel scope link src 10.88.0.1 linkdown | |
76 | 172.21.0.0/20 via 172.21.3.189 dev tun0 | |
77 | 172.21.1.0/20 via 172.21.3.189 dev tun0 | |
78 | 172.21.2.1 via 172.21.3.189 dev tun0 | |
79 | 172.21.3.1 dev tun0 proto kernel scope link src 172.21.3.2 | |
80 | 172.21.4.0/24 via 172.21.3.1 dev tun0 | |
81 | 172.21.5.0/24 via 172.21.3.1 dev tun0 | |
82 | 172.21.6.0/24 via 172.21.3.1 dev tun0 | |
83 | 172.21.7.0/24 via 172.21.3.1 dev tun0 | |
84 | 192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown | |
85 | """, | |
86 | { | |
87 | '10.3.64.0/24': ['10.3.64.23', '10.3.64.27'], | |
88 | '10.88.0.0/16': ['10.88.0.1'], | |
89 | '172.21.3.1': ['172.21.3.2'], | |
90 | '192.168.122.0/24': ['192.168.122.1']} | |
91 | ), | |
92 | ]) | |
f6b5b4d7 TL |
93 | def test_parse_ipv4_route(self, test_input, expected): |
94 | assert cd._parse_ipv4_route(test_input) == expected | |
95 | ||
96 | @pytest.mark.parametrize("test_routes, test_ips, expected", [ | |
97 | ( | |
98 | """ | |
99 | ::1 dev lo proto kernel metric 256 pref medium | |
100 | fdbc:7574:21fe:9200::/64 dev wlp2s0 proto ra metric 600 pref medium | |
101 | fdd8:591e:4969:6363::/64 dev wlp2s0 proto ra metric 600 pref medium | |
102 | fde4:8dba:82e1::/64 dev eth1 proto kernel metric 256 expires 1844sec pref medium | |
103 | fe80::/64 dev tun0 proto kernel metric 256 pref medium | |
104 | fe80::/64 dev wlp2s0 proto kernel metric 600 pref medium | |
105 | default dev tun0 proto static metric 50 pref medium | |
106 | default via fe80::2480:28ec:5097:3fe2 dev wlp2s0 proto ra metric 20600 pref medium | |
107 | """, | |
108 | """ | |
109 | 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000 | |
110 | inet6 ::1/128 scope host | |
111 | valid_lft forever preferred_lft forever | |
112 | 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000 | |
113 | inet6 fdd8:591e:4969:6363:4c52:cafe:8dd4:dc4/64 scope global temporary dynamic | |
114 | valid_lft 86394sec preferred_lft 14394sec | |
115 | inet6 fdbc:7574:21fe:9200:4c52:cafe:8dd4:dc4/64 scope global temporary dynamic | |
116 | valid_lft 6745sec preferred_lft 3145sec | |
117 | inet6 fdd8:591e:4969:6363:103a:abcd:af1f:57f3/64 scope global temporary deprecated dynamic | |
118 | valid_lft 86394sec preferred_lft 0sec | |
119 | inet6 fdbc:7574:21fe:9200:103a:abcd:af1f:57f3/64 scope global temporary deprecated dynamic | |
120 | valid_lft 6745sec preferred_lft 0sec | |
121 | inet6 fdd8:591e:4969:6363:a128:1234:2bdd:1b6f/64 scope global temporary deprecated dynamic | |
122 | valid_lft 86394sec preferred_lft 0sec | |
123 | inet6 fdbc:7574:21fe:9200:a128:1234:2bdd:1b6f/64 scope global temporary deprecated dynamic | |
124 | valid_lft 6745sec preferred_lft 0sec | |
125 | inet6 fdd8:591e:4969:6363:d581:4321:380b:3905/64 scope global temporary deprecated dynamic | |
126 | valid_lft 86394sec preferred_lft 0sec | |
127 | inet6 fdbc:7574:21fe:9200:d581:4321:380b:3905/64 scope global temporary deprecated dynamic | |
128 | valid_lft 6745sec preferred_lft 0sec | |
129 | inet6 fe80::1111:2222:3333:4444/64 scope link noprefixroute | |
130 | valid_lft forever preferred_lft forever | |
131 | inet6 fde4:8dba:82e1:0:ec4a:e402:e9df:b357/64 scope global temporary dynamic | |
132 | valid_lft 1074sec preferred_lft 1074sec | |
133 | inet6 fde4:8dba:82e1:0:5054:ff:fe72:61af/64 scope global dynamic mngtmpaddr | |
134 | valid_lft 1074sec preferred_lft 1074sec | |
135 | 12: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 state UNKNOWN qlen 100 | |
136 | inet6 fe80::cafe:cafe:cafe:cafe/64 scope link stable-privacy | |
137 | valid_lft forever preferred_lft forever | |
138 | """, | |
139 | { | |
140 | "::1": ["::1"], | |
141 | "fdbc:7574:21fe:9200::/64": ["fdbc:7574:21fe:9200:4c52:cafe:8dd4:dc4", | |
142 | "fdbc:7574:21fe:9200:103a:abcd:af1f:57f3", | |
143 | "fdbc:7574:21fe:9200:a128:1234:2bdd:1b6f", | |
144 | "fdbc:7574:21fe:9200:d581:4321:380b:3905"], | |
145 | "fdd8:591e:4969:6363::/64": ["fdd8:591e:4969:6363:4c52:cafe:8dd4:dc4", | |
146 | "fdd8:591e:4969:6363:103a:abcd:af1f:57f3", | |
147 | "fdd8:591e:4969:6363:a128:1234:2bdd:1b6f", | |
148 | "fdd8:591e:4969:6363:d581:4321:380b:3905"], | |
149 | "fde4:8dba:82e1::/64": ["fde4:8dba:82e1:0:ec4a:e402:e9df:b357", | |
150 | "fde4:8dba:82e1:0:5054:ff:fe72:61af"], | |
151 | "fe80::/64": ["fe80::1111:2222:3333:4444", | |
152 | "fe80::cafe:cafe:cafe:cafe"] | |
153 | } | |
154 | )]) | |
155 | def test_parse_ipv6_route(self, test_routes, test_ips, expected): | |
156 | assert cd._parse_ipv6_route(test_routes, test_ips) == expected | |
157 | ||
158 | def test_is_ipv6(self): | |
159 | cd.logger = mock.Mock() | |
160 | for good in ("[::1]", "::1", | |
161 | "fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"): | |
162 | assert cd.is_ipv6(good) | |
163 | for bad in ("127.0.0.1", | |
164 | "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffg", | |
165 | "1:2:3:4:5:6:7:8:9", "fd00::1::1", "[fg::1]"): | |
166 | assert not cd.is_ipv6(bad) | |
167 | ||
168 | def test_unwrap_ipv6(self): | |
169 | def unwrap_test(address, expected): | |
170 | assert cd.unwrap_ipv6(address) == expected | |
171 | ||
172 | tests = [ | |
173 | ('::1', '::1'), ('[::1]', '::1'), | |
174 | ('[fde4:8dba:82e1:0:5054:ff:fe6a:357]', 'fde4:8dba:82e1:0:5054:ff:fe6a:357'), | |
175 | ('can actually be any string', 'can actually be any string'), | |
176 | ('[but needs to be stripped] ', '[but needs to be stripped] ')] | |
177 | for address, expected in tests: | |
178 | unwrap_test(address, expected) | |
179 | ||
180 | @mock.patch('cephadm.call_throws') | |
181 | @mock.patch('cephadm.get_parm') | |
182 | def test_registry_login(self, get_parm, call_throws): | |
183 | ||
184 | # test normal valid login with url, username and password specified | |
185 | call_throws.return_value = '', '', 0 | |
186 | args = cd._parse_args(['registry-login', '--registry-url', 'sample-url', '--registry-username', 'sample-user', '--registry-password', 'sample-pass']) | |
187 | cd.args = args | |
188 | retval = cd.command_registry_login() | |
189 | assert retval == 0 | |
190 | ||
191 | # test bad login attempt with invalid arguments given | |
192 | args = cd._parse_args(['registry-login', '--registry-url', 'bad-args-url']) | |
193 | cd.args = args | |
194 | with pytest.raises(Exception) as e: | |
195 | assert cd.command_registry_login() | |
196 | assert str(e.value) == ('Invalid custom registry arguments received. To login to a custom registry include ' | |
197 | '--registry-url, --registry-username and --registry-password options or --registry-json option') | |
198 | ||
199 | # test normal valid login with json file | |
200 | get_parm.return_value = {"url": "sample-url", "username": "sample-username", "password": "sample-password"} | |
201 | args = cd._parse_args(['registry-login', '--registry-json', 'sample-json']) | |
202 | cd.args = args | |
203 | retval = cd.command_registry_login() | |
204 | assert retval == 0 | |
205 | ||
206 | # test bad login attempt with bad json file | |
207 | get_parm.return_value = {"bad-json": "bad-json"} | |
208 | args = cd._parse_args(['registry-login', '--registry-json', 'sample-json']) | |
209 | cd.args = args | |
210 | with pytest.raises(Exception) as e: | |
211 | assert cd.command_registry_login() | |
212 | assert str(e.value) == ("json provided for custom registry login did not include all necessary fields. " | |
213 | "Please setup json file as\n" | |
214 | "{\n" | |
215 | " \"url\": \"REGISTRY_URL\",\n" | |
216 | " \"username\": \"REGISTRY_USERNAME\",\n" | |
217 | " \"password\": \"REGISTRY_PASSWORD\"\n" | |
218 | "}\n") | |
219 | ||
220 | # test login attempt with valid arguments where login command fails | |
221 | call_throws.side_effect = Exception | |
222 | args = cd._parse_args(['registry-login', '--registry-url', 'sample-url', '--registry-username', 'sample-user', '--registry-password', 'sample-pass']) | |
223 | cd.args = args | |
224 | with pytest.raises(Exception) as e: | |
225 | cd.command_registry_login() | |
226 | assert str(e.value) == "Failed to login to custom registry @ sample-url as sample-user with given password" |