Merge ~hloeung/smtp-relay-charm:mx into smtp-relay-charm:master
- Git
- lp:~hloeung/smtp-relay-charm
- mx
- Merge into master
Proposed by
Haw Loeung
Status: | Merged |
---|---|
Approved by: | Haw Loeung |
Approved revision: | 123e54e62417f3dad87ae94310795763b41e8b18 |
Merged at revision: | c6c92aa26414b5c6f3f34f1daf5853f7af24ee73 |
Proposed branch: | ~hloeung/smtp-relay-charm:mx |
Merge into: | smtp-relay-charm:master |
Diff against target: |
401 lines (+296/-5) 7 files modified
config.yaml (+18/-0) reactive/smtp_relay.py (+12/-4) templates/postfix_main_cf.tmpl (+9/-1) tests/unit/files/postfix_main_transport_maps.cf (+59/-0) tests/unit/files/postfix_main_transport_maps_with_header_checks.cf (+61/-0) tests/unit/files/postfix_main_transport_maps_with_virtual_alias_maps.cf (+61/-0) tests/unit/test_smtp_relay.py (+76/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Colin Misare | Approve | ||
Canonical IS Reviewers | Pending | ||
Review via email: mp+416357@code.launchpad.net |
Commit message
Add support for running as MX by allowing transport and virtual alias maps
Description of the change
To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : | # |
Revision history for this message
Colin Misare (cmisare) wrote : | # |
One nitpick but LGTM either way
review:
Approve
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : | # |
Change successfully merged at revision c6c92aa26414b5c
Revision history for this message
Joel Sing (jsing) : | # |
Revision history for this message
Haw Loeung (hloeung) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/config.yaml b/config.yaml |
2 | index 19eab05..b3d6470 100644 |
3 | --- a/config.yaml |
4 | +++ b/config.yaml |
5 | @@ -159,3 +159,21 @@ options: |
6 | outbound to other MTAs as it may cause deliverability issues. |
7 | |
8 | http://www.postfix.org/postconf.5.html#smtpd_tls_security_level |
9 | + transport_maps: |
10 | + type: string |
11 | + default: '' |
12 | + description: | |
13 | + Optional lookup tables with mappings from recipient address to |
14 | + message delivery transport or next-hop destination (use 'MANUAL' |
15 | + to indicate it is managed outside of juju configs). |
16 | + |
17 | + http://www.postfix.org/postconf.5.html#transport_maps |
18 | + virtual_alias_maps: |
19 | + type: string |
20 | + default: '' |
21 | + description: | |
22 | + Optional lookup tables that alias specific mail addresses or |
23 | + domains to other local or remote addresses (use 'MANUAL' to |
24 | + indicate it is managed outside of juju configs). |
25 | + |
26 | + http://www.postfix.org/postconf.5.html#virtual_alias_maps |
27 | diff --git a/reactive/smtp_relay.py b/reactive/smtp_relay.py |
28 | index 8fb59c3..58ec8b3 100644 |
29 | --- a/reactive/smtp_relay.py |
30 | +++ b/reactive/smtp_relay.py |
31 | @@ -122,6 +122,8 @@ def configure_smtp_auth(dovecot_config='/etc/dovecot/dovecot.conf', dovecot_user |
32 | 'config.changed.tls_policy_maps', |
33 | 'config.changed.tls_protocols', |
34 | 'config.changed.tls_security_level', |
35 | + 'config.changed.transport_maps', |
36 | + 'config.changed.virtual_alias_maps', |
37 | ) |
38 | def config_changed(): |
39 | reactive.clear_flag('smtp-relay.configured') |
40 | @@ -152,7 +154,9 @@ def _create_update_map(content, postmap): |
41 | os.utime(pmfname, None) |
42 | changed = True |
43 | |
44 | - if not content.startswith('MANUAL'): |
45 | + if content.startswith('MANUAL'): |
46 | + hookenv.log('Map {} manually managed'.format(pmfname)) |
47 | + else: |
48 | contents = JUJU_HEADER + content + '\n' |
49 | changed = _write_file(contents, pmfname) or changed |
50 | |
51 | @@ -220,6 +224,8 @@ def configure_smtp_relay(postfix_conf_dir='/etc/postfix', tls_dh_params='/etc/ss |
52 | 'tls_exclude_ciphers': config['tls_exclude_ciphers'], |
53 | 'tls_protocols': config['tls_protocols'], |
54 | 'tls_security_level': config['tls_security_level'], |
55 | + 'transport_maps': True if config['transport_maps'] else False, |
56 | + 'virtual_alias_maps': True if config['virtual_alias_maps'] else False, |
57 | } |
58 | base = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) |
59 | env = jinja2.Environment(loader=jinja2.FileSystemLoader(base)) |
60 | @@ -237,6 +243,8 @@ def configure_smtp_relay(postfix_conf_dir='/etc/postfix', tls_dh_params='/etc/ss |
61 | 'sender_access': 'hash:{}'.format(os.path.join(postfix_conf_dir, 'access')), |
62 | 'sender_login_maps': 'hash:{}'.format(os.path.join(postfix_conf_dir, 'sender_login')), |
63 | 'tls_policy_maps': 'hash:{}'.format(os.path.join(postfix_conf_dir, 'tls_policy')), |
64 | + 'transport_maps': 'hash:{}'.format(os.path.join(postfix_conf_dir, 'transport')), |
65 | + 'virtual_alias_maps': 'hash:{}'.format(os.path.join(postfix_conf_dir, 'virtual_alias')), |
66 | } |
67 | sender_access_content = config['restrict_sender_access'] |
68 | if sender_access_content and not sender_access_content.startswith('MANUAL'): |
69 | @@ -251,6 +259,8 @@ def configure_smtp_relay(postfix_conf_dir='/etc/postfix', tls_dh_params='/etc/ss |
70 | 'sender_access': sender_access_content, |
71 | 'sender_login_maps': config['sender_login_maps'], |
72 | 'tls_policy_maps': config['tls_policy_maps'], |
73 | + 'transport_maps': config['transport_maps'], |
74 | + 'virtual_alias_maps': config['virtual_alias_maps'], |
75 | } |
76 | |
77 | # Ensure various maps exists before starting/restarting postfix. |
78 | @@ -365,9 +375,7 @@ def _write_file(source, dest_path, perms=0o644, owner=None, group=None): |
79 | """Write file only on changes and return True if changes written.""" |
80 | # Compare and only write out file on change. |
81 | dest = '' |
82 | - if not os.path.exists(dest_path): |
83 | - with open(dest_path, 'a') as f: |
84 | - os.utime(dest_path, None) |
85 | + |
86 | try: |
87 | with open(dest_path, 'r') as f: |
88 | dest = f.read() |
89 | diff --git a/templates/postfix_main_cf.tmpl b/templates/postfix_main_cf.tmpl |
90 | index a555c4b..c92ee6f 100644 |
91 | --- a/templates/postfix_main_cf.tmpl |
92 | +++ b/templates/postfix_main_cf.tmpl |
93 | @@ -98,6 +98,14 @@ restricted = check_recipient_access hash:/etc/postfix/restricted_recipients, rej |
94 | smtpd_milters = {{milter}} |
95 | non_smtpd_milters = {{milter}} |
96 | {% endif -%} |
97 | -{% if header_checks %} |
98 | + |
99 | +{%- if header_checks %} |
100 | header_checks = regexp:/etc/postfix/header_checks |
101 | +{% endif -%} |
102 | + |
103 | +{%- if transport_maps %} |
104 | +transport_maps = hash:/etc/postfix/transport |
105 | +{% endif %} |
106 | +{%- if virtual_alias_maps %} |
107 | +virtual_alias_maps = hash:/etc/postfix/virtual_alias |
108 | {% endif %} |
109 | diff --git a/tests/unit/files/postfix_main_transport_maps.cf b/tests/unit/files/postfix_main_transport_maps.cf |
110 | new file mode 100644 |
111 | index 0000000..a80d6b8 |
112 | --- /dev/null |
113 | +++ b/tests/unit/files/postfix_main_transport_maps.cf |
114 | @@ -0,0 +1,59 @@ |
115 | +## This file is Juju managed - do not edit by hand # |
116 | + |
117 | + |
118 | +smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu) |
119 | +biff = no |
120 | + |
121 | +append_dot_mydomain = no |
122 | + |
123 | +readme_directory = no |
124 | + |
125 | +# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 2 on |
126 | +# fresh installs. |
127 | +compatibility_level = 2 |
128 | + |
129 | +# TLS parameters |
130 | +tls_preempt_cipherlist = yes |
131 | +smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem |
132 | +smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key |
133 | +smtpd_tls_dh1024_param_file = /etc/ssl/private/dhparams.pem |
134 | +smtpd_tls_ciphers = HIGH |
135 | +smtpd_tls_exclude_ciphers = aNULL, eNULL, DES, 3DES, MD5, RC4, CAMELLIA |
136 | +smtpd_tls_loglevel = 1 |
137 | +smtpd_tls_mandatory_ciphers = HIGH |
138 | +smtpd_tls_mandatory_protocols = !SSLv2 !SSLv3 |
139 | +smtpd_tls_protocols = !SSLv2 !SSLv3 |
140 | +smtpd_tls_received_header = yes |
141 | +smtpd_tls_security_level = may |
142 | +smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache |
143 | + |
144 | +smtp_tls_CApath = /etc/ssl/certs |
145 | +smtp_tls_loglevel = 1 |
146 | +smtp_tls_security_level = may |
147 | +smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache |
148 | + |
149 | +message_size_limit = 61440000 |
150 | +strict_rfc821_envelopes = yes |
151 | +smtpd_client_connection_count_limit = 100 |
152 | +smtpd_helo_required = yes |
153 | +smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination |
154 | +myhostname = juju-87625f-hloeung-94.openstacklocal |
155 | +alias_maps = hash:/etc/aliases |
156 | +alias_database = hash:/etc/aliases |
157 | +mydestination = $myhostname, juju-87625f-hloeung-94, localhost.localdomain, localhost |
158 | +relayhost = |
159 | +mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 |
160 | +mailbox_size_limit = 0 |
161 | +recipient_delimiter = + |
162 | +inet_interfaces = all |
163 | +inet_protocols = all |
164 | + |
165 | +broken_sasl_auth_clients = yes |
166 | +smtpd_sasl_auth_enable = yes |
167 | +smtpd_sasl_security_options = noanonymous |
168 | +smtpd_sasl_type = dovecot |
169 | +smtpd_sasl_path = private/auth |
170 | +smtpd_tls_auth_only = yes |
171 | +smtpd_sender_restrictions = reject_unknown_sender_domain, check_sender_access hash:/etc/postfix/access |
172 | + |
173 | +transport_maps = hash:/etc/postfix/transport |
174 | diff --git a/tests/unit/files/postfix_main_transport_maps_with_header_checks.cf b/tests/unit/files/postfix_main_transport_maps_with_header_checks.cf |
175 | new file mode 100644 |
176 | index 0000000..34e055c |
177 | --- /dev/null |
178 | +++ b/tests/unit/files/postfix_main_transport_maps_with_header_checks.cf |
179 | @@ -0,0 +1,61 @@ |
180 | +## This file is Juju managed - do not edit by hand # |
181 | + |
182 | + |
183 | +smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu) |
184 | +biff = no |
185 | + |
186 | +append_dot_mydomain = no |
187 | + |
188 | +readme_directory = no |
189 | + |
190 | +# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 2 on |
191 | +# fresh installs. |
192 | +compatibility_level = 2 |
193 | + |
194 | +# TLS parameters |
195 | +tls_preempt_cipherlist = yes |
196 | +smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem |
197 | +smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key |
198 | +smtpd_tls_dh1024_param_file = /etc/ssl/private/dhparams.pem |
199 | +smtpd_tls_ciphers = HIGH |
200 | +smtpd_tls_exclude_ciphers = aNULL, eNULL, DES, 3DES, MD5, RC4, CAMELLIA |
201 | +smtpd_tls_loglevel = 1 |
202 | +smtpd_tls_mandatory_ciphers = HIGH |
203 | +smtpd_tls_mandatory_protocols = !SSLv2 !SSLv3 |
204 | +smtpd_tls_protocols = !SSLv2 !SSLv3 |
205 | +smtpd_tls_received_header = yes |
206 | +smtpd_tls_security_level = may |
207 | +smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache |
208 | + |
209 | +smtp_tls_CApath = /etc/ssl/certs |
210 | +smtp_tls_loglevel = 1 |
211 | +smtp_tls_security_level = may |
212 | +smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache |
213 | + |
214 | +message_size_limit = 61440000 |
215 | +strict_rfc821_envelopes = yes |
216 | +smtpd_client_connection_count_limit = 100 |
217 | +smtpd_helo_required = yes |
218 | +smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination |
219 | +myhostname = juju-87625f-hloeung-94.openstacklocal |
220 | +alias_maps = hash:/etc/aliases |
221 | +alias_database = hash:/etc/aliases |
222 | +mydestination = $myhostname, juju-87625f-hloeung-94, localhost.localdomain, localhost |
223 | +relayhost = |
224 | +mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 |
225 | +mailbox_size_limit = 0 |
226 | +recipient_delimiter = + |
227 | +inet_interfaces = all |
228 | +inet_protocols = all |
229 | + |
230 | +broken_sasl_auth_clients = yes |
231 | +smtpd_sasl_auth_enable = yes |
232 | +smtpd_sasl_security_options = noanonymous |
233 | +smtpd_sasl_type = dovecot |
234 | +smtpd_sasl_path = private/auth |
235 | +smtpd_tls_auth_only = yes |
236 | +smtpd_sender_restrictions = reject_unknown_sender_domain, check_sender_access hash:/etc/postfix/access |
237 | + |
238 | +header_checks = regexp:/etc/postfix/header_checks |
239 | + |
240 | +transport_maps = hash:/etc/postfix/transport |
241 | diff --git a/tests/unit/files/postfix_main_transport_maps_with_virtual_alias_maps.cf b/tests/unit/files/postfix_main_transport_maps_with_virtual_alias_maps.cf |
242 | new file mode 100644 |
243 | index 0000000..6049e7c |
244 | --- /dev/null |
245 | +++ b/tests/unit/files/postfix_main_transport_maps_with_virtual_alias_maps.cf |
246 | @@ -0,0 +1,61 @@ |
247 | +## This file is Juju managed - do not edit by hand # |
248 | + |
249 | + |
250 | +smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu) |
251 | +biff = no |
252 | + |
253 | +append_dot_mydomain = no |
254 | + |
255 | +readme_directory = no |
256 | + |
257 | +# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 2 on |
258 | +# fresh installs. |
259 | +compatibility_level = 2 |
260 | + |
261 | +# TLS parameters |
262 | +tls_preempt_cipherlist = yes |
263 | +smtpd_tls_cert_file = /etc/ssl/certs/ssl-cert-snakeoil.pem |
264 | +smtpd_tls_key_file = /etc/ssl/private/ssl-cert-snakeoil.key |
265 | +smtpd_tls_dh1024_param_file = /etc/ssl/private/dhparams.pem |
266 | +smtpd_tls_ciphers = HIGH |
267 | +smtpd_tls_exclude_ciphers = aNULL, eNULL, DES, 3DES, MD5, RC4, CAMELLIA |
268 | +smtpd_tls_loglevel = 1 |
269 | +smtpd_tls_mandatory_ciphers = HIGH |
270 | +smtpd_tls_mandatory_protocols = !SSLv2 !SSLv3 |
271 | +smtpd_tls_protocols = !SSLv2 !SSLv3 |
272 | +smtpd_tls_received_header = yes |
273 | +smtpd_tls_security_level = may |
274 | +smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache |
275 | + |
276 | +smtp_tls_CApath = /etc/ssl/certs |
277 | +smtp_tls_loglevel = 1 |
278 | +smtp_tls_security_level = may |
279 | +smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache |
280 | + |
281 | +message_size_limit = 61440000 |
282 | +strict_rfc821_envelopes = yes |
283 | +smtpd_client_connection_count_limit = 100 |
284 | +smtpd_helo_required = yes |
285 | +smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination |
286 | +myhostname = juju-87625f-hloeung-94.openstacklocal |
287 | +alias_maps = hash:/etc/aliases |
288 | +alias_database = hash:/etc/aliases |
289 | +mydestination = $myhostname, juju-87625f-hloeung-94, localhost.localdomain, localhost |
290 | +relayhost = |
291 | +mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 |
292 | +mailbox_size_limit = 0 |
293 | +recipient_delimiter = + |
294 | +inet_interfaces = all |
295 | +inet_protocols = all |
296 | + |
297 | +broken_sasl_auth_clients = yes |
298 | +smtpd_sasl_auth_enable = yes |
299 | +smtpd_sasl_security_options = noanonymous |
300 | +smtpd_sasl_type = dovecot |
301 | +smtpd_sasl_path = private/auth |
302 | +smtpd_tls_auth_only = yes |
303 | +smtpd_sender_restrictions = reject_unknown_sender_domain, check_sender_access hash:/etc/postfix/access |
304 | + |
305 | +transport_maps = hash:/etc/postfix/transport |
306 | + |
307 | +virtual_alias_maps = hash:/etc/postfix/virtual_alias |
308 | diff --git a/tests/unit/test_smtp_relay.py b/tests/unit/test_smtp_relay.py |
309 | index 366a24b..f9cdd61 100644 |
310 | --- a/tests/unit/test_smtp_relay.py |
311 | +++ b/tests/unit/test_smtp_relay.py |
312 | @@ -77,6 +77,8 @@ class TestCharm(unittest.TestCase): |
313 | 'tls_policy_maps': '', |
314 | 'tls_protocols': '!SSLv2 !SSLv3', |
315 | 'tls_security_level': 'may', |
316 | + 'transport_maps': '', |
317 | + 'virtual_alias_maps': '', |
318 | } |
319 | |
320 | patcher = mock.patch('charmhelpers.core.hookenv.close_port') |
321 | @@ -905,6 +907,80 @@ someplace.local encrypt |
322 | @mock.patch('charms.reactive.set_flag') |
323 | @mock.patch('reactive.smtp_relay._get_autocert_cn') |
324 | @mock.patch('reactive.smtp_relay._get_milters') |
325 | + @mock.patch('subprocess.call') |
326 | + def test_configure_smtp_relay_config_transport_maps(self, call, get_milters, get_cn, set_flag, clear_flag): |
327 | + postfix_main_cf = os.path.join(self.tmpdir, 'main.cf') |
328 | + postfix_transport_maps = os.path.join(self.tmpdir, 'transport') |
329 | + get_cn.return_value = '' |
330 | + get_milters.return_value = '' |
331 | + self.mock_config.return_value['transport_maps'] = '.mydomain.local smtp:[smtp.mydomain.local]' |
332 | + smtp_relay.configure_smtp_relay(self.tmpdir) |
333 | + with open('tests/unit/files/postfix_main_transport_maps.cf', 'r', encoding='utf-8') as f: |
334 | + want = f.read() |
335 | + with open(postfix_main_cf, 'r', encoding='utf-8') as f: |
336 | + got = f.read() |
337 | + self.assertEqual(want, got) |
338 | + want = smtp_relay.JUJU_HEADER + '.mydomain.local smtp:[smtp.mydomain.local]' + "\n" |
339 | + with open(postfix_transport_maps, 'r', encoding='utf-8') as f: |
340 | + got = f.read() |
341 | + self.assertEqual(want, got) |
342 | + |
343 | + @mock.patch('charms.reactive.clear_flag') |
344 | + @mock.patch('charms.reactive.set_flag') |
345 | + @mock.patch('reactive.smtp_relay._get_autocert_cn') |
346 | + @mock.patch('reactive.smtp_relay._get_milters') |
347 | + @mock.patch('subprocess.call') |
348 | + def test_configure_smtp_relay_config_transport_maps_with_header_checks( |
349 | + self, call, get_milters, get_cn, set_flag, clear_flag |
350 | + ): |
351 | + postfix_main_cf = os.path.join(self.tmpdir, 'main.cf') |
352 | + postfix_transport_maps = os.path.join(self.tmpdir, 'transport') |
353 | + get_cn.return_value = '' |
354 | + get_milters.return_value = '' |
355 | + self.mock_config.return_value['header_checks'] = '/^Received:/ HOLD' |
356 | + self.mock_config.return_value['transport_maps'] = '.mydomain.local smtp:[smtp.mydomain.local]' |
357 | + smtp_relay.configure_smtp_relay(self.tmpdir) |
358 | + with open('tests/unit/files/postfix_main_transport_maps_with_header_checks.cf', 'r', encoding='utf-8') as f: |
359 | + want = f.read() |
360 | + with open(postfix_main_cf, 'r', encoding='utf-8') as f: |
361 | + got = f.read() |
362 | + self.assertEqual(want, got) |
363 | + want = smtp_relay.JUJU_HEADER + '.mydomain.local smtp:[smtp.mydomain.local]' + "\n" |
364 | + with open(postfix_transport_maps, 'r', encoding='utf-8') as f: |
365 | + got = f.read() |
366 | + self.assertEqual(want, got) |
367 | + |
368 | + @mock.patch('charms.reactive.clear_flag') |
369 | + @mock.patch('charms.reactive.set_flag') |
370 | + @mock.patch('reactive.smtp_relay._get_autocert_cn') |
371 | + @mock.patch('reactive.smtp_relay._get_milters') |
372 | + @mock.patch('subprocess.call') |
373 | + def test_configure_smtp_relay_config_transport_maps_with_virtual_alias_maps( |
374 | + self, call, get_milters, get_cn, set_flag, clear_flag |
375 | + ): |
376 | + postfix_main_cf = os.path.join(self.tmpdir, 'main.cf') |
377 | + postfix_virtual_alias_maps = os.path.join(self.tmpdir, 'virtual_alias') |
378 | + get_cn.return_value = '' |
379 | + get_milters.return_value = '' |
380 | + self.mock_config.return_value['transport_maps'] = '.mydomain.local smtp:[smtp.mydomain.local]' |
381 | + self.mock_config.return_value['virtual_alias_maps'] = 'abuse@mydomain.local sysadmin@mydomain.local' |
382 | + smtp_relay.configure_smtp_relay(self.tmpdir) |
383 | + with open( |
384 | + 'tests/unit/files/postfix_main_transport_maps_with_virtual_alias_maps.cf', 'r', encoding='utf-8' |
385 | + ) as f: |
386 | + want = f.read() |
387 | + with open(postfix_main_cf, 'r', encoding='utf-8') as f: |
388 | + got = f.read() |
389 | + self.assertEqual(want, got) |
390 | + want = smtp_relay.JUJU_HEADER + 'abuse@mydomain.local sysadmin@mydomain.local' + "\n" |
391 | + with open(postfix_virtual_alias_maps, 'r', encoding='utf-8') as f: |
392 | + got = f.read() |
393 | + self.assertEqual(want, got) |
394 | + |
395 | + @mock.patch('charms.reactive.clear_flag') |
396 | + @mock.patch('charms.reactive.set_flag') |
397 | + @mock.patch('reactive.smtp_relay._get_autocert_cn') |
398 | + @mock.patch('reactive.smtp_relay._get_milters') |
399 | @mock.patch('reactive.smtp_relay._write_file') |
400 | @mock.patch('subprocess.call') |
401 | def test_configure_smtp_relay_flags(self, call, write_file, get_milters, get_cn, set_flag, clear_flag): |
This merge proposal is being monitored by mergebot. Change the status to Approved to merge.