Merge ~xavpaice/charm-nagios:lint-20.08 into ~nagios-charmers/charm-nagios:master

Proposed by Xav Paice
Status: Merged
Merged at revision: b27a20af88bd66c4c5d43b0903b30fa69fd6abd5
Proposed branch: ~xavpaice/charm-nagios:lint-20.08
Merge into: ~nagios-charmers/charm-nagios:master
Prerequisite: ~xavpaice/charm-nagios:blacken-20.08
Diff against target: 1205 lines (+185/-107)
9 files modified
hooks/common.py (+62/-11)
hooks/monitors_relation_changed.py (+25/-12)
hooks/upgrade_charm.py (+62/-25)
hooks/website_relation_joined.py (+3/-6)
tests/functional/conftest.py (+25/-19)
tests/functional/test_config.py (+6/-8)
tests/functional/test_deploy.py (+1/-0)
tests/unit/test_website_relation_joined.py (+1/-0)
tox.ini (+0/-26)
Reviewer Review Type Date Requested Status
Alvaro Uria (community) Approve
Celia Wang Approve
Review via email: mp+388634@code.launchpad.net

Commit message

Extra Linting completed for 20.08 charm release

To post a comment you must log in.
Revision history for this message
Celia Wang (ziyiwang) wrote :

LGTM

review: Approve
Revision history for this message
Alvaro Uria (aluria) wrote :

+1 this and the other 2 related MPs (blacken and makefile)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/hooks/common.py b/hooks/common.py
index 3bff942..b320880 100644
--- a/hooks/common.py
+++ b/hooks/common.py
@@ -1,17 +1,17 @@
1import subprocess
2import socket
3import os1import os
4import os.path2import os.path
5import re3import re
6import shutil4import shutil
5import socket
6import subprocess
7import tempfile7import tempfile
88
9from charmhelpers.core.hookenv import (9from charmhelpers.core.hookenv import (
10 config,
10 log,11 log,
11 network_get,12 network_get,
12 network_get_primary_address,13 network_get_primary_address,
13 unit_get,14 unit_get,
14 config,
15)15)
1616
17from pynag import Model17from pynag import Model
@@ -28,16 +28,18 @@ PLUGIN_PATH = "/usr/lib/nagios/plugins"
28Model.cfg_file = INPROGRESS_CFG28Model.cfg_file = INPROGRESS_CFG
29Model.pynag_directory = INPROGRESS_CONF_D29Model.pynag_directory = INPROGRESS_CONF_D
3030
31reduce_RE = re.compile(r"[\W_]")31REDUCE_RE = re.compile(r"[\W_]")
3232
3333
34def check_ip(n):34def check_ip(n):
35 try:35 try:
36 socket.inet_pton(socket.AF_INET, n)36 socket.inet_pton(socket.AF_INET, n)
37
37 return True38 return True
38 except socket.error:39 except socket.error:
39 try:40 try:
40 socket.inet_pton(socket.AF_INET6, n)41 socket.inet_pton(socket.AF_INET6, n)
42
41 return True43 return True
42 except socket.error:44 except socket.error:
43 return False45 return False
@@ -48,10 +50,12 @@ def get_local_ingress_address(binding="website"):
48 log("Getting hostname for binding %s" % binding)50 log("Getting hostname for binding %s" % binding)
49 try:51 try:
50 network_info = network_get(binding)52 network_info = network_get(binding)
53
51 if network_info is not None and "ingress-addresses" in network_info:54 if network_info is not None and "ingress-addresses" in network_info:
52 log("Using ingress-addresses")55 log("Using ingress-addresses")
53 hostname = network_info["ingress-addresses"][0]56 hostname = network_info["ingress-addresses"][0]
54 log(hostname)57 log(hostname)
58
55 return hostname59 return hostname
56 except NotImplementedError:60 except NotImplementedError:
57 # We'll fallthrough to the Pre 2.3 code below.61 # We'll fallthrough to the Pre 2.3 code below.
@@ -66,29 +70,36 @@ def get_local_ingress_address(binding="website"):
66 hostname = unit_get("private-address")70 hostname = unit_get("private-address")
67 log("Using unit_get private address")71 log("Using unit_get private address")
68 log(hostname)72 log(hostname)
73
69 return hostname74 return hostname
7075
7176
72def get_remote_relation_attr(remote_unit, attr_name, relation_id=None):77def get_remote_relation_attr(remote_unit, attr_name, relation_id=None):
73 args = ["relation-get", attr_name, remote_unit]78 args = ["relation-get", attr_name, remote_unit]
79
74 if relation_id is not None:80 if relation_id is not None:
75 args.extend(["-r", relation_id])81 args.extend(["-r", relation_id])
82
76 return subprocess.check_output(args).strip()83 return subprocess.check_output(args).strip()
7784
7885
79def get_ip_and_hostname(remote_unit, relation_id=None):86def get_ip_and_hostname(remote_unit, relation_id=None):
80 hostname = get_remote_relation_attr(remote_unit, "ingress-address", relation_id)87 hostname = get_remote_relation_attr(remote_unit, "ingress-address", relation_id)
88
81 if hostname is None or not len(hostname):89 if hostname is None or not len(hostname):
82 hostname = get_remote_relation_attr(remote_unit, "private-address", relation_id)90 hostname = get_remote_relation_attr(remote_unit, "private-address", relation_id)
8391
84 if hostname is None or not len(hostname):92 if hostname is None or not len(hostname):
85 log("relation-get failed")93 log("relation-get failed")
94
86 return 295 return 2
96
87 if check_ip(hostname):97 if check_ip(hostname):
88 # Some providers don't provide hostnames, so use the remote unit name.98 # Some providers don't provide hostnames, so use the remote unit name.
89 ip_address = hostname99 ip_address = hostname
90 else:100 else:
91 ip_address = socket.getaddrinfo(hostname, None)[0][4][0]101 ip_address = socket.getaddrinfo(hostname, None)[0][4][0]
102
92 return (ip_address, remote_unit.replace("/", "-"))103 return (ip_address, remote_unit.replace("/", "-"))
93104
94105
@@ -98,11 +109,13 @@ def refresh_hostgroups(): # noqa:C901
98 hosts = [x["host_name"] for x in Model.Host.objects.all if x["host_name"]]109 hosts = [x["host_name"] for x in Model.Host.objects.all if x["host_name"]]
99110
100 hgroups = {}111 hgroups = {}
112
101 for host in hosts:113 for host in hosts:
102 try:114 try:
103 (service, unit_id) = host.rsplit("-", 1)115 (service, unit_id) = host.rsplit("-", 1)
104 except ValueError:116 except ValueError:
105 continue117 continue
118
106 if service in hgroups:119 if service in hgroups:
107 hgroups[service].append(host)120 hgroups[service].append(host)
108 else:121 else:
@@ -114,6 +127,7 @@ def refresh_hostgroups(): # noqa:C901
114127
115 # Delete the ones not in hgroups128 # Delete the ones not in hgroups
116 to_delete = set(auto_hgroups).difference(set(hgroups.keys()))129 to_delete = set(auto_hgroups).difference(set(hgroups.keys()))
130
117 for hgroup_name in to_delete:131 for hgroup_name in to_delete:
118 try:132 try:
119 hgroup = Model.Hostgroup.objects.get_by_shortname(hgroup_name)133 hgroup = Model.Hostgroup.objects.get_by_shortname(hgroup_name)
@@ -138,7 +152,7 @@ def _make_check_command(args):
138 args = [str(arg) for arg in args]152 args = [str(arg) for arg in args]
139 # There is some worry of collision, but the uniqueness of the initial153 # There is some worry of collision, but the uniqueness of the initial
140 # command should be enough.154 # command should be enough.
141 signature = reduce_RE.sub("_", "".join([os.path.basename(arg) for arg in args]))155 signature = REDUCE_RE.sub("_", "".join([os.path.basename(arg) for arg in args]))
142 Model.Command.objects.reload_cache()156 Model.Command.objects.reload_cache()
143 try:157 try:
144 cmd = Model.Command.objects.get_by_shortname(signature)158 cmd = Model.Command.objects.get_by_shortname(signature)
@@ -147,6 +161,7 @@ def _make_check_command(args):
147 cmd.set_attribute("command_name", signature)161 cmd.set_attribute("command_name", signature)
148 cmd.set_attribute("command_line", " ".join(args))162 cmd.set_attribute("command_line", " ".join(args))
149 cmd.save()163 cmd.save()
164
150 return signature165 return signature
151166
152167
@@ -163,19 +178,23 @@ def customize_http(service, name, extra):
163 path = extra.get("path", "/")178 path = extra.get("path", "/")
164 args = [port, path]179 args = [port, path]
165 cmd_args = [plugin, "-p", '"$ARG1$"', "-u", '"$ARG2$"']180 cmd_args = [plugin, "-p", '"$ARG1$"', "-u", '"$ARG2$"']
181
166 if "status" in extra:182 if "status" in extra:
167 _extend_args(args, cmd_args, "-e", extra["status"])183 _extend_args(args, cmd_args, "-e", extra["status"])
184
168 if "host" in extra:185 if "host" in extra:
169 _extend_args(args, cmd_args, "-H", extra["host"])186 _extend_args(args, cmd_args, "-H", extra["host"])
170 cmd_args.extend(("-I", "$HOSTADDRESS$"))187 cmd_args.extend(("-I", "$HOSTADDRESS$"))
171 else:188 else:
172 cmd_args.extend(("-H", "$HOSTADDRESS$"))189 cmd_args.extend(("-H", "$HOSTADDRESS$"))
173 check_timeout = config("check_timeout")190 check_timeout = config("check_timeout")
191
174 if check_timeout is not None:192 if check_timeout is not None:
175 cmd_args.extend(("-t", check_timeout))193 cmd_args.extend(("-t", check_timeout))
176 check_command = _make_check_command(cmd_args)194 check_command = _make_check_command(cmd_args)
177 cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))195 cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))
178 service.set_attribute("check_command", cmd)196 service.set_attribute("check_command", cmd)
197
179 return True198 return True
180199
181200
@@ -183,16 +202,20 @@ def customize_mysql(service, name, extra):
183 plugin = os.path.join(PLUGIN_PATH, "check_mysql")202 plugin = os.path.join(PLUGIN_PATH, "check_mysql")
184 args = []203 args = []
185 cmd_args = [plugin, "-H", "$HOSTADDRESS$"]204 cmd_args = [plugin, "-H", "$HOSTADDRESS$"]
205
186 if "user" in extra:206 if "user" in extra:
187 _extend_args(args, cmd_args, "-u", extra["user"])207 _extend_args(args, cmd_args, "-u", extra["user"])
208
188 if "password" in extra:209 if "password" in extra:
189 _extend_args(args, cmd_args, "-p", extra["password"])210 _extend_args(args, cmd_args, "-p", extra["password"])
190 check_timeout = config("check_timeout")211 check_timeout = config("check_timeout")
212
191 if check_timeout is not None:213 if check_timeout is not None:
192 cmd_args.extend(("-t", check_timeout))214 cmd_args.extend(("-t", check_timeout))
193 check_command = _make_check_command(cmd_args)215 check_command = _make_check_command(cmd_args)
194 cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))216 cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))
195 service.set_attribute("check_command", cmd)217 service.set_attribute("check_command", cmd)
218
196 return True219 return True
197220
198221
@@ -201,11 +224,13 @@ def customize_pgsql(service, name, extra):
201 args = []224 args = []
202 cmd_args = [plugin, "-H", "$HOSTADDRESS$"]225 cmd_args = [plugin, "-H", "$HOSTADDRESS$"]
203 check_timeout = config("check_timeout")226 check_timeout = config("check_timeout")
227
204 if check_timeout is not None:228 if check_timeout is not None:
205 cmd_args.extend(("-t", check_timeout))229 cmd_args.extend(("-t", check_timeout))
206 check_command = _make_check_command(cmd_args)230 check_command = _make_check_command(cmd_args)
207 cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))231 cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))
208 service.set_attribute("check_command", cmd)232 service.set_attribute("check_command", cmd)
233
209 return True234 return True
210235
211236
@@ -213,6 +238,7 @@ def customize_nrpe(service, name, extra):
213 plugin = os.path.join(PLUGIN_PATH, "check_nrpe")238 plugin = os.path.join(PLUGIN_PATH, "check_nrpe")
214 args = []239 args = []
215 cmd_args = [plugin, "-H", "$HOSTADDRESS$"]240 cmd_args = [plugin, "-H", "$HOSTADDRESS$"]
241
216 if name in ("mem", "swap"):242 if name in ("mem", "swap"):
217 cmd_args.extend(("-c", "check_%s" % name))243 cmd_args.extend(("-c", "check_%s" % name))
218 elif "command" in extra:244 elif "command" in extra:
@@ -220,61 +246,77 @@ def customize_nrpe(service, name, extra):
220 else:246 else:
221 cmd_args.extend(("-c", extra))247 cmd_args.extend(("-c", extra))
222 check_timeout = config("check_timeout")248 check_timeout = config("check_timeout")
249
223 if check_timeout is not None:250 if check_timeout is not None:
224 cmd_args.extend(("-t", check_timeout))251 cmd_args.extend(("-t", check_timeout))
225 check_command = _make_check_command(cmd_args)252 check_command = _make_check_command(cmd_args)
226 cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))253 cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))
227 service.set_attribute("check_command", cmd)254 service.set_attribute("check_command", cmd)
255
228 return True256 return True
229257
230258
231def customize_rpc(service, name, extra):259def customize_rpc(service, name, extra):
232 """ Customize the check_rpc plugin to check things like nfs."""260 """Customize the check_rpc plugin to check things like nfs."""
233 plugin = os.path.join(PLUGIN_PATH, "check_rpc")261 plugin = os.path.join(PLUGIN_PATH, "check_rpc")
234 args = []262 args = []
235 # /usr/lib/nagios/plugins/check_rpc -H <host> -C <rpc_command>263 # /usr/lib/nagios/plugins/check_rpc -H <host> -C <rpc_command>
236 cmd_args = [plugin, "-H", "$HOSTADDRESS$"]264 cmd_args = [plugin, "-H", "$HOSTADDRESS$"]
265
237 if "rpc_command" in extra:266 if "rpc_command" in extra:
238 cmd_args.extend(("-C", extra["rpc_command"]))267 cmd_args.extend(("-C", extra["rpc_command"]))
268
239 if "program_version" in extra:269 if "program_version" in extra:
240 cmd_args.extend(("-c", extra["program_version"]))270 cmd_args.extend(("-c", extra["program_version"]))
241271
242 check_command = _make_check_command(cmd_args)272 check_command = _make_check_command(cmd_args)
243 cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))273 cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))
244 service.set_attribute("check_command", cmd)274 service.set_attribute("check_command", cmd)
275
245 return True276 return True
246277
247278
248def customize_tcp(service, name, extra):279def customize_tcp(service, name, extra):
249 """ Customize tcp can be used to check things like memcached. """280 """Customize tcp can be used to check things like memcached."""
250 plugin = os.path.join(PLUGIN_PATH, "check_tcp")281 plugin = os.path.join(PLUGIN_PATH, "check_tcp")
251 args = []282 args = []
252 # /usr/lib/nagios/plugins/check_tcp -H <host> -E283 # /usr/lib/nagios/plugins/check_tcp -H <host> -E
253 cmd_args = [plugin, "-H", "$HOSTADDRESS$", "-E"]284 cmd_args = [plugin, "-H", "$HOSTADDRESS$", "-E"]
285
254 if "port" in extra:286 if "port" in extra:
255 cmd_args.extend(("-p", extra["port"]))287 cmd_args.extend(("-p", extra["port"]))
288
256 if "string" in extra:289 if "string" in extra:
257 cmd_args.extend(("-s", "'{}'".format(extra["string"])))290 cmd_args.extend(("-s", "'{}'".format(extra["string"])))
291
258 if "expect" in extra:292 if "expect" in extra:
259 cmd_args.extend(("-e", extra["expect"]))293 cmd_args.extend(("-e", extra["expect"]))
294
260 if "warning" in extra:295 if "warning" in extra:
261 cmd_args.extend(("-w", extra["warning"]))296 cmd_args.extend(("-w", extra["warning"]))
297
262 if "critical" in extra:298 if "critical" in extra:
263 cmd_args.extend(("-c", extra["critical"]))299 cmd_args.extend(("-c", extra["critical"]))
300
264 if "timeout" in extra:301 if "timeout" in extra:
265 cmd_args.extend(("-t", extra["timeout"]))302 cmd_args.extend(("-t", extra["timeout"]))
266 check_timeout = config("check_timeout")303 check_timeout = config("check_timeout")
304
267 if check_timeout is not None:305 if check_timeout is not None:
268 cmd_args.extend(("-t", check_timeout))306 cmd_args.extend(("-t", check_timeout))
269307
270 check_command = _make_check_command(cmd_args)308 check_command = _make_check_command(cmd_args)
271 cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))309 cmd = "%s!%s" % (check_command, "!".join([str(x) for x in args]))
272 service.set_attribute("check_command", cmd)310 service.set_attribute("check_command", cmd)
311
273 return True312 return True
274313
275314
276def customize_service(service, family, name, extra):315def customize_service(service, family, name, extra):
277 """ The monitors.yaml names are mapped to methods that customize services. """316 """Map names to service methods.
317
318 The monitors.yaml names are mapped to methods that customize services.
319 """
278 customs = {320 customs = {
279 "http": customize_http,321 "http": customize_http,
280 "mysql": customize_mysql,322 "mysql": customize_mysql,
@@ -283,17 +325,19 @@ def customize_service(service, family, name, extra):
283 "rpc": customize_rpc,325 "rpc": customize_rpc,
284 "pgsql": customize_pgsql,326 "pgsql": customize_pgsql,
285 }327 }
328
286 if family in customs:329 if family in customs:
287 return customs[family](service, name, extra)330 return customs[family](service, name, extra)
331
288 return False332 return False
289333
290334
291def update_localhost():335def update_localhost():
292 """ Update the localhost definition to use the ubuntu icons."""336 """Update the localhost definition to use the ubuntu icons."""
293
294 Model.cfg_file = MAIN_NAGIOS_CFG337 Model.cfg_file = MAIN_NAGIOS_CFG
295 Model.pynag_directory = os.path.join(MAIN_NAGIOS_DIR, "conf.d")338 Model.pynag_directory = os.path.join(MAIN_NAGIOS_DIR, "conf.d")
296 hosts = Model.Host.objects.filter(host_name="localhost", object_type="host")339 hosts = Model.Host.objects.filter(host_name="localhost", object_type="host")
340
297 for host in hosts:341 for host in hosts:
298 host.icon_image = "base/ubuntu.png"342 host.icon_image = "base/ubuntu.png"
299 host.icon_image_alt = "Ubuntu Linux"343 host.icon_image_alt = "Ubuntu Linux"
@@ -318,6 +362,7 @@ def get_pynag_host(target_id, owner_unit=None, owner_relation=None):
318 host.save()362 host.save()
319 host = Model.Host.objects.get_by_shortname(target_id)363 host = Model.Host.objects.get_by_shortname(target_id)
320 apply_host_policy(target_id, owner_unit, owner_relation)364 apply_host_policy(target_id, owner_unit, owner_relation)
365
321 return host366 return host
322367
323368
@@ -325,6 +370,7 @@ def get_pynag_service(target_id, service_name):
325 services = Model.Service.objects.filter(370 services = Model.Service.objects.filter(
326 host_name=target_id, service_description=service_name371 host_name=target_id, service_description=service_name
327 )372 )
373
328 if len(services) == 0:374 if len(services) == 0:
329 service = Model.Service()375 service = Model.Service()
330 service.set_filename(CHARM_CFG)376 service.set_filename(CHARM_CFG)
@@ -333,6 +379,7 @@ def get_pynag_service(target_id, service_name):
333 service.set_attribute("use", "generic-service")379 service.set_attribute("use", "generic-service")
334 else:380 else:
335 service = services[0]381 service = services[0]
382
336 return service383 return service
337384
338385
@@ -369,6 +416,7 @@ def initialize_inprogress_config():
369 shutil.rmtree(INPROGRESS_DIR)416 shutil.rmtree(INPROGRESS_DIR)
370 shutil.copytree(MAIN_NAGIOS_DIR, INPROGRESS_DIR)417 shutil.copytree(MAIN_NAGIOS_DIR, INPROGRESS_DIR)
371 _replace_in_config(MAIN_NAGIOS_DIR, INPROGRESS_DIR)418 _replace_in_config(MAIN_NAGIOS_DIR, INPROGRESS_DIR)
419
372 if os.path.exists(CHARM_CFG):420 if os.path.exists(CHARM_CFG):
373 os.unlink(CHARM_CFG)421 os.unlink(CHARM_CFG)
374422
@@ -376,10 +424,13 @@ def initialize_inprogress_config():
376def flush_inprogress_config():424def flush_inprogress_config():
377 if not os.path.exists(INPROGRESS_DIR):425 if not os.path.exists(INPROGRESS_DIR):
378 return426 return
427
379 if os.path.exists(MAIN_NAGIOS_BAK):428 if os.path.exists(MAIN_NAGIOS_BAK):
380 shutil.rmtree(MAIN_NAGIOS_BAK)429 shutil.rmtree(MAIN_NAGIOS_BAK)
430
381 if os.path.exists(MAIN_NAGIOS_DIR):431 if os.path.exists(MAIN_NAGIOS_DIR):
382 shutil.move(MAIN_NAGIOS_DIR, MAIN_NAGIOS_BAK)432 shutil.move(MAIN_NAGIOS_DIR, MAIN_NAGIOS_BAK)
383 shutil.move(INPROGRESS_DIR, MAIN_NAGIOS_DIR)433 shutil.move(INPROGRESS_DIR, MAIN_NAGIOS_DIR)
384 # now that directory has been changed need to update the config file to reflect the real stuff..434 # now that directory has been changed need to update the config file to
435 # reflect the real stuff..
385 _commit_in_config(INPROGRESS_DIR, MAIN_NAGIOS_DIR)436 _commit_in_config(INPROGRESS_DIR, MAIN_NAGIOS_DIR)
diff --git a/hooks/monitors_relation_changed.py b/hooks/monitors_relation_changed.py
index e3d5a5a..6df3303 100755
--- a/hooks/monitors_relation_changed.py
+++ b/hooks/monitors_relation_changed.py
@@ -16,36 +16,32 @@
16# You should have received a copy of the GNU General Public License16# You should have received a copy of the GNU General Public License
17# along with this program. If not, see <http://www.gnu.org/licenses/>.17# along with this program. If not, see <http://www.gnu.org/licenses/>.
1818
19import sys
20import os19import os
21import yaml
22import re20import re
21import sys
23from collections import defaultdict22from collections import defaultdict
2423
25from charmhelpers.core.hookenv import (24from charmhelpers.core.hookenv import (
26 relation_get,25 DEBUG,
27 ingress_address,26 ingress_address,
27 log,
28 related_units,28 related_units,
29 relation_get,
29 relation_ids,30 relation_ids,
30 log,
31 DEBUG,
32)31)
3332
34from common import (33from common import (
35 customize_service,34 customize_service,
35 flush_inprogress_config,
36 get_pynag_host,36 get_pynag_host,
37 get_pynag_service,37 get_pynag_service,
38 refresh_hostgroups,
39 initialize_inprogress_config,38 initialize_inprogress_config,
40 flush_inprogress_config,39 refresh_hostgroups,
41)40)
4241
42import yaml
4343
44REQUIRED_REL_DATA_KEYS = [44REQUIRED_REL_DATA_KEYS = ["target-address", "monitors", "target-id"]
45 "target-address",
46 "monitors",
47 "target-id",
48]
4945
5046
51def _prepare_relation_data(unit, rid):47def _prepare_relation_data(unit, rid):
@@ -56,6 +52,7 @@ def _prepare_relation_data(unit, rid):
56 unit, rid52 unit, rid
57 )53 )
58 log(msg, level=DEBUG)54 log(msg, level=DEBUG)
55
59 return {}56 return {}
6057
61 if rid.split(":")[0] == "nagios":58 if rid.split(":")[0] == "nagios":
@@ -76,6 +73,7 @@ def _prepare_relation_data(unit, rid):
76 key, unit, rid73 key, unit, rid
77 )74 )
78 log(msg, level=DEBUG)75 log(msg, level=DEBUG)
76
79 return {}77 return {}
8078
81 return relation_data79 return relation_data
@@ -83,10 +81,12 @@ def _prepare_relation_data(unit, rid):
8381
84def _collect_relation_data():82def _collect_relation_data():
85 all_relations = defaultdict(dict)83 all_relations = defaultdict(dict)
84
86 for relname in ["nagios", "monitors"]:85 for relname in ["nagios", "monitors"]:
87 for relid in relation_ids(relname):86 for relid in relation_ids(relname):
88 for unit in related_units(relid):87 for unit in related_units(relid):
89 relation_data = _prepare_relation_data(unit=unit, rid=relid)88 relation_data = _prepare_relation_data(unit=unit, rid=relid)
89
90 if relation_data:90 if relation_data:
91 all_relations[relid][unit] = relation_data91 all_relations[relid][unit] = relation_data
9292
@@ -98,8 +98,10 @@ def main(argv): # noqa: C901
98 # and target-address' so the hook can be tested without being in a hook98 # and target-address' so the hook can be tested without being in a hook
99 # context.99 # context.
100 #100 #
101
101 if len(argv) > 1:102 if len(argv) > 1:
102 relation_settings = {"monitors": open(argv[1]).read(), "target-id": argv[2]}103 relation_settings = {"monitors": open(argv[1]).read(), "target-id": argv[2]}
104
103 if len(argv) > 3:105 if len(argv) > 3:
104 relation_settings["target-address"] = argv[3]106 relation_settings["target-address"] = argv[3]
105 all_relations = {"monitors:99": {"testing/0": relation_settings}}107 all_relations = {"monitors:99": {"testing/0": relation_settings}}
@@ -108,11 +110,13 @@ def main(argv): # noqa: C901
108110
109 # Hack to work around http://pad.lv/1025478111 # Hack to work around http://pad.lv/1025478
110 targets_with_addresses = set()112 targets_with_addresses = set()
113
111 for relid, units in all_relations.iteritems():114 for relid, units in all_relations.iteritems():
112 for unit, relation_settings in units.items():115 for unit, relation_settings in units.items():
113 if "target-id" in relation_settings:116 if "target-id" in relation_settings:
114 targets_with_addresses.add(relation_settings["target-id"])117 targets_with_addresses.add(relation_settings["target-id"])
115 new_all_relations = {}118 new_all_relations = {}
119
116 for relid, units in all_relations.iteritems():120 for relid, units in all_relations.iteritems():
117 for unit, relation_settings in units.items():121 for unit, relation_settings in units.items():
118 if relation_settings["target-id"] in targets_with_addresses:122 if relation_settings["target-id"] in targets_with_addresses:
@@ -124,11 +128,14 @@ def main(argv): # noqa: C901
124 initialize_inprogress_config()128 initialize_inprogress_config()
125 # make a dict of machine ids to target-id hostnames129 # make a dict of machine ids to target-id hostnames
126 all_hosts = {}130 all_hosts = {}
131
127 for relid, units in all_relations.items():132 for relid, units in all_relations.items():
128 for unit, relation_settings in units.iteritems():133 for unit, relation_settings in units.iteritems():
129 machine_id = relation_settings.get("machine_id", None)134 machine_id = relation_settings.get("machine_id", None)
135
130 if machine_id:136 if machine_id:
131 all_hosts[machine_id] = relation_settings["target-id"]137 all_hosts[machine_id] = relation_settings["target-id"]
138
132 for relid, units in all_relations.items():139 for relid, units in all_relations.items():
133 apply_relation_config(relid, units, all_hosts)140 apply_relation_config(relid, units, all_hosts)
134 refresh_hostgroups()141 refresh_hostgroups()
@@ -142,10 +149,13 @@ def apply_relation_config(relid, units, all_hosts): # noqa: C901
142 target_id = relation_settings["target-id"]149 target_id = relation_settings["target-id"]
143 machine_id = relation_settings.get("machine_id", None)150 machine_id = relation_settings.get("machine_id", None)
144 parent_host = None151 parent_host = None
152
145 if machine_id:153 if machine_id:
146 container_regex = re.compile(r"(\d+)/lx[cd]/\d+")154 container_regex = re.compile(r"(\d+)/lx[cd]/\d+")
155
147 if container_regex.search(machine_id):156 if container_regex.search(machine_id):
148 parent_machine = container_regex.search(machine_id).group(1)157 parent_machine = container_regex.search(machine_id).group(1)
158
149 if parent_machine in all_hosts:159 if parent_machine in all_hosts:
150 parent_host = all_hosts[parent_machine]160 parent_host = all_hosts[parent_machine]
151161
@@ -159,9 +169,11 @@ def apply_relation_config(relid, units, all_hosts): # noqa: C901
159169
160 # Output nagios config170 # Output nagios config
161 host = get_pynag_host(target_id)171 host = get_pynag_host(target_id)
172
162 if not target_address:173 if not target_address:
163 raise Exception("No Target Address provied by NRPE service!")174 raise Exception("No Target Address provied by NRPE service!")
164 host.set_attribute("address", target_address)175 host.set_attribute("address", target_address)
176
165 if parent_host:177 if parent_host:
166 # We assume that we only want one parent and will overwrite any178 # We assume that we only want one parent and will overwrite any
167 # existing parents for this host.179 # existing parents for this host.
@@ -172,6 +184,7 @@ def apply_relation_config(relid, units, all_hosts): # noqa: C901
172 for mon_name, mon in mons.iteritems():184 for mon_name, mon in mons.iteritems():
173 service_name = "%s-%s" % (target_id, mon_name)185 service_name = "%s-%s" % (target_id, mon_name)
174 service = get_pynag_service(target_id, service_name)186 service = get_pynag_service(target_id, service_name)
187
175 if customize_service(service, mon_family, mon_name, mon):188 if customize_service(service, mon_family, mon_name, mon):
176 service.save()189 service.save()
177 else:190 else:
diff --git a/hooks/upgrade_charm.py b/hooks/upgrade_charm.py
index 5091f9a..ca410ef 100755
--- a/hooks/upgrade_charm.py
+++ b/hooks/upgrade_charm.py
@@ -3,25 +3,26 @@
3# Rewritten from bash to python 3/2/2014 for charm helper inclusion3# Rewritten from bash to python 3/2/2014 for charm helper inclusion
4# of SSL-Everywhere!4# of SSL-Everywhere!
5import base645import base64
6from jinja2 import Template6import errno
7import glob7import glob
8import grp
8import os9import os
9
10# import re
11import pwd10import pwd
12import grp
13import string
14import stat
15import errno
16import shutil11import shutil
12import stat
13import string
17import subprocess14import subprocess
18import yaml15
16from charmhelpers import fetch
19from charmhelpers.contrib import ssl17from charmhelpers.contrib import ssl
20from charmhelpers.core import hookenv, host18from charmhelpers.core import hookenv, host
21from charmhelpers import fetch
2219
23from common import update_localhost20from common import update_localhost
2421
22from jinja2 import Template
23
24import yaml
25
25# Gather facts26# Gather facts
26legacy_relations = hookenv.config("legacy")27legacy_relations = hookenv.config("legacy")
27extra_config = hookenv.config("extraconfig")28extra_config = hookenv.config("extraconfig")
@@ -55,7 +56,7 @@ SSL_CONFIGURED = ssl_config in ["on", "only", "true"]
5556
5657
57def warn_legacy_relations():58def warn_legacy_relations():
58 """Checks the charm relations for legacy relations.59 """Check the charm relations for legacy relations.
5960
60 Inserts warnings into the log about legacy relations, as they will be removed61 Inserts warnings into the log about legacy relations, as they will be removed
61 in the future62 in the future
@@ -70,7 +71,7 @@ def warn_legacy_relations():
7071
7172
72def parse_extra_contacts(yaml_string):73def parse_extra_contacts(yaml_string):
73 """Parses a list of extra Nagios contacts from a YAML string.74 """Parse a list of extra Nagios contacts from a YAML string.
7475
75 Does basic sanitization only76 Does basic sanitization only
76 """77 """
@@ -82,6 +83,7 @@ def parse_extra_contacts(yaml_string):
8283
83 try:84 try:
84 extra_contacts_raw = yaml.load(yaml_string, Loader=yaml.SafeLoader) or []85 extra_contacts_raw = yaml.load(yaml_string, Loader=yaml.SafeLoader) or []
86
85 if not isinstance(extra_contacts_raw, list):87 if not isinstance(extra_contacts_raw, list):
86 raise ValueError("not a list")88 raise ValueError("not a list")
8789
@@ -90,6 +92,7 @@ def parse_extra_contacts(yaml_string):
90 hookenv.log(92 hookenv.log(
91 "Contact {} is missing fields.".format(contact), hookenv.WARNING93 "Contact {} is missing fields.".format(contact), hookenv.WARNING
92 )94 )
95
93 continue96 continue
9497
95 if set(contact["name"]) > set(valid_name_chars):98 if set(contact["name"]) > set(valid_name_chars):
@@ -97,10 +100,12 @@ def parse_extra_contacts(yaml_string):
97 "Contact name {} is illegal".format(contact["name"]),100 "Contact name {} is illegal".format(contact["name"]),
98 hookenv.WARNING,101 hookenv.WARNING,
99 )102 )
103
100 continue104 continue
101105
102 if "\n" in (contact["host"] + contact["service"]):106 if "\n" in (contact["host"] + contact["service"]):
103 hookenv.log("Line breaks not allowed in commands", hookenv.WARNING)107 hookenv.log("Line breaks not allowed in commands", hookenv.WARNING)
108
104 continue109 continue
105110
106 contact["name"] = contact["name"].lower()111 contact["name"] = contact["name"].lower()
@@ -111,6 +116,7 @@ def parse_extra_contacts(yaml_string):
111 hookenv.log(116 hookenv.log(
112 'Invalid "extra_contacts" configuration: {}'.format(e), hookenv.WARNING117 'Invalid "extra_contacts" configuration: {}'.format(e), hookenv.WARNING
113 )118 )
119
114 if len(extra_contacts_raw) != len(extra_contacts):120 if len(extra_contacts_raw) != len(extra_contacts):
115 hookenv.log(121 hookenv.log(
116 "Invalid extra_contacts config, found {} contacts defined, "122 "Invalid extra_contacts config, found {} contacts defined, "
@@ -125,10 +131,12 @@ def parse_extra_contacts(yaml_string):
125# proper nagios3 configuration file, otherwise remove the config131# proper nagios3 configuration file, otherwise remove the config
126def write_extra_config():132def write_extra_config():
127 # Be predjudice about this - remove the file always.133 # Be predjudice about this - remove the file always.
134
128 if host.file_hash("/etc/nagios3/conf.d/extra.cfg") is not None:135 if host.file_hash("/etc/nagios3/conf.d/extra.cfg") is not None:
129 os.remove("/etc/nagios3/conf.d/extra.cfg")136 os.remove("/etc/nagios3/conf.d/extra.cfg")
130 # If we have a config, then write it. the hook reconfiguration will137 # If we have a config, then write it. the hook reconfiguration will
131 # handle the details138 # handle the details
139
132 if extra_config is not None:140 if extra_config is not None:
133 host.write_file("/etc/nagios3/conf.d/extra.cfg", extra_config)141 host.write_file("/etc/nagios3/conf.d/extra.cfg", extra_config)
134142
@@ -150,6 +158,7 @@ def fixpath(path):
150 if os.path.isdir(path):158 if os.path.isdir(path):
151 st = os.stat(path)159 st = os.stat(path)
152 os.chmod(path, st.st_mode | stat.S_IXOTH)160 os.chmod(path, st.st_mode | stat.S_IXOTH)
161
153 if path != "/":162 if path != "/":
154 fixpath(os.path.split(path)[0])163 fixpath(os.path.split(path)[0])
155164
@@ -163,6 +172,7 @@ def enable_livestatus_config():
163 # Make the directory and fix perms on it172 # Make the directory and fix perms on it
164 hookenv.log("Fixing perms on livestatus_path")173 hookenv.log("Fixing perms on livestatus_path")
165 livestatus_dir = os.path.dirname(livestatus_path)174 livestatus_dir = os.path.dirname(livestatus_path)
175
166 if not os.path.isdir(livestatus_dir):176 if not os.path.isdir(livestatus_dir):
167 hookenv.log("Making path for livestatus_dir")177 hookenv.log("Making path for livestatus_dir")
168 mkdir_p(livestatus_dir)178 mkdir_p(livestatus_dir)
@@ -202,16 +212,16 @@ def enable_pagerduty_config():
202 }212 }
203213
204 with open("hooks/templates/pagerduty_nagios_cfg.tmpl", "r") as f:214 with open("hooks/templates/pagerduty_nagios_cfg.tmpl", "r") as f:
205 templateDef = f.read()215 template_def = f.read()
206216
207 t = Template(templateDef)217 t = Template(template_def)
208 with open(pagerduty_cfg, "w") as f:218 with open(pagerduty_cfg, "w") as f:
209 f.write(t.render(template_values))219 f.write(t.render(template_values))
210220
211 with open("hooks/templates/nagios-pagerduty-flush-cron.tmpl", "r") as f2:221 with open("hooks/templates/nagios-pagerduty-flush-cron.tmpl", "r") as f2:
212 templateDef = f2.read()222 template_def = f2.read()
213223
214 t2 = Template(templateDef)224 t2 = Template(template_def)
215 with open(pagerduty_cron, "w") as f2:225 with open(pagerduty_cron, "w") as f2:
216 f2.write(t2.render(template_values))226 f2.write(t2.render(template_values))
217227
@@ -219,6 +229,7 @@ def enable_pagerduty_config():
219 shutil.copy("files/pagerduty_nagios.pl", "/usr/local/bin/pagerduty_nagios.pl")229 shutil.copy("files/pagerduty_nagios.pl", "/usr/local/bin/pagerduty_nagios.pl")
220230
221 # Create the pagerduty queue dir231 # Create the pagerduty queue dir
232
222 if not os.path.isdir(pagerduty_path):233 if not os.path.isdir(pagerduty_path):
223 hookenv.log("Making path for pagerduty_path")234 hookenv.log("Making path for pagerduty_path")
224 mkdir_p(pagerduty_path)235 mkdir_p(pagerduty_path)
@@ -228,14 +239,18 @@ def enable_pagerduty_config():
228 os.chown(pagerduty_path, uid, gid)239 os.chown(pagerduty_path, uid, gid)
229 else:240 else:
230 # Clean up the files if we don't want pagerduty241 # Clean up the files if we don't want pagerduty
242
231 if os.path.isfile(pagerduty_cfg):243 if os.path.isfile(pagerduty_cfg):
232 os.remove(pagerduty_cfg)244 os.remove(pagerduty_cfg)
245
233 if os.path.isfile(pagerduty_cron):246 if os.path.isfile(pagerduty_cron):
234 os.remove(pagerduty_cron)247 os.remove(pagerduty_cron)
235248
236 # Update contacts for admin249 # Update contacts for admin
250
237 if enable_pagerduty:251 if enable_pagerduty:
238 # avoid duplicates252 # avoid duplicates
253
239 if "pagerduty" not in contactgroup_members:254 if "pagerduty" not in contactgroup_members:
240 forced_contactgroup_members.append("pagerduty")255 forced_contactgroup_members.append("pagerduty")
241256
@@ -249,6 +264,7 @@ def enable_traps_config():
249 if os.path.isfile(traps_cfg):264 if os.path.isfile(traps_cfg):
250 os.remove(traps_cfg)265 os.remove(traps_cfg)
251 hookenv.log("Send traps feature is disabled")266 hookenv.log("Send traps feature is disabled")
267
252 return268 return
253269
254 hookenv.log("Send traps feature is enabled, target address is %s" % send_traps_to)270 hookenv.log("Send traps feature is enabled, target address is %s" % send_traps_to)
@@ -259,9 +275,9 @@ def enable_traps_config():
259 template_values = {"send_traps_to": send_traps_to}275 template_values = {"send_traps_to": send_traps_to}
260276
261 with open("hooks/templates/traps.tmpl", "r") as f:277 with open("hooks/templates/traps.tmpl", "r") as f:
262 templateDef = f.read()278 template_def = f.read()
263279
264 t = Template(templateDef)280 t = Template(template_def)
265 with open(traps_cfg, "w") as f:281 with open(traps_cfg, "w") as f:
266 f.write(t.render(template_values))282 f.write(t.render(template_values))
267283
@@ -271,17 +287,20 @@ def update_contacts():
271 admin_members = ""287 admin_members = ""
272 contacts = []288 contacts = []
273 admin_email = list(filter(None, set(hookenv.config("admin_email").split(","))))289 admin_email = list(filter(None, set(hookenv.config("admin_email").split(","))))
290
274 if len(admin_email) == 0:291 if len(admin_email) == 0:
275 hookenv.log("admin_email is unset, this isn't valid config")292 hookenv.log("admin_email is unset, this isn't valid config")
276 hookenv.status_set("blocked", "admin_email is not configured")293 hookenv.status_set("blocked", "admin_email is not configured")
277 exit(1)294 exit(1)
278 hookenv.status_set("active", "ready")295 hookenv.status_set("active", "ready")
296
279 if len(admin_email) == 1:297 if len(admin_email) == 1:
280 hookenv.log("Setting one admin email address '%s'" % admin_email[0])298 hookenv.log("Setting one admin email address '%s'" % admin_email[0])
281 contacts = [{"contact_name": "root", "alias": "Root", "email": admin_email[0]}]299 contacts = [{"contact_name": "root", "alias": "Root", "email": admin_email[0]}]
282 elif len(admin_email) > 1:300 elif len(admin_email) > 1:
283 hookenv.log("Setting %d admin email addresses" % len(admin_email))301 hookenv.log("Setting %d admin email addresses" % len(admin_email))
284 contacts = []302 contacts = []
303
285 for email in admin_email:304 for email in admin_email:
286 contact_name = email.replace("@", "").replace(".", "").lower()305 contact_name = email.replace("@", "").replace(".", "").lower()
287 contact_alias = contact_name.capitalize()306 contact_alias = contact_name.capitalize()
@@ -292,6 +311,7 @@ def update_contacts():
292 admin_members = ", ".join([c["contact_name"] for c in contacts])311 admin_members = ", ".join([c["contact_name"] for c in contacts])
293312
294 resulting_members = contactgroup_members313 resulting_members = contactgroup_members
314
295 if admin_members:315 if admin_members:
296 # if multiple admin emails are passed ignore contactgroup_members316 # if multiple admin emails are passed ignore contactgroup_members
297 resulting_members = admin_members317 resulting_members = admin_members
@@ -338,8 +358,10 @@ def update_contacts():
338358
339def ssl_configured():359def ssl_configured():
340 allowed_options = ["on", "only"]360 allowed_options = ["on", "only"]
361
341 if str(ssl_config).lower() in allowed_options:362 if str(ssl_config).lower() in allowed_options:
342 return True363 return True
364
343 return False365 return False
344366
345367
@@ -359,8 +381,10 @@ chain_file = "/etc/ssl/certs/%s.csr" % (cert_domain)
359def check_ssl_files():381def check_ssl_files():
360 key = os.path.exists(deploy_key_path)382 key = os.path.exists(deploy_key_path)
361 cert = os.path.exists(deploy_cert_path)383 cert = os.path.exists(deploy_cert_path)
384
362 if key is False or cert is False:385 if key is False or cert is False:
363 return False386 return False
387
364 return True388 return True
365389
366390
@@ -370,9 +394,11 @@ def decode_ssl_keys():
370 hookenv.log("Writing key from config ssl_key: %s" % key_file)394 hookenv.log("Writing key from config ssl_key: %s" % key_file)
371 with open(key_file, "w") as f:395 with open(key_file, "w") as f:
372 f.write(str(base64.b64decode(hookenv.config("ssl_key"))))396 f.write(str(base64.b64decode(hookenv.config("ssl_key"))))
397
373 if hookenv.config("ssl_cert"):398 if hookenv.config("ssl_cert"):
374 with open(cert_file, "w") as f:399 with open(cert_file, "w") as f:
375 f.write(str(base64.b64decode(hookenv.config("ssl_cert"))))400 f.write(str(base64.b64decode(hookenv.config("ssl_cert"))))
401
376 if hookenv.config("ssl_chain"):402 if hookenv.config("ssl_chain"):
377 with open(chain_file, "w") as f:403 with open(chain_file, "w") as f:
378 f.write(str(base64.b64decode(hookenv.config("ssl_cert"))))404 f.write(str(base64.b64decode(hookenv.config("ssl_cert"))))
@@ -382,10 +408,13 @@ def enable_ssl():
382 # Set the basename of all ssl files408 # Set the basename of all ssl files
383409
384 # Validate that we have configs, and generate a self signed certificate.410 # Validate that we have configs, and generate a self signed certificate.
411
385 if not hookenv.config("ssl_cert"):412 if not hookenv.config("ssl_cert"):
386 # bail if keys already exist413 # bail if keys already exist
414
387 if os.path.exists(cert_file):415 if os.path.exists(cert_file):
388 hookenv.log("Keys exist, not creating keys!", "WARNING")416 hookenv.log("Keys exist, not creating keys!", "WARNING")
417
389 return418 return
390 # Generate a self signed key using CharmHelpers419 # Generate a self signed key using CharmHelpers
391 hookenv.log("Generating Self Signed Certificate", "INFO")420 hookenv.log("Generating Self Signed Certificate", "INFO")
@@ -405,6 +434,7 @@ def update_config():
405 local_host_name = "nagios"434 local_host_name = "nagios"
406 principal_unitname = hookenv.principal_unit()435 principal_unitname = hookenv.principal_unit()
407 # Fallback to using "primary" if it exists.436 # Fallback to using "primary" if it exists.
437
408 if principal_unitname:438 if principal_unitname:
409 local_host_name = principal_unitname439 local_host_name = principal_unitname
410 else:440 else:
@@ -437,16 +467,16 @@ def update_config():
437 }467 }
438468
439 with open("hooks/templates/nagios-cfg.tmpl", "r") as f:469 with open("hooks/templates/nagios-cfg.tmpl", "r") as f:
440 templateDef = f.read()470 template_def = f.read()
441471
442 t = Template(templateDef)472 t = Template(template_def)
443 with open(nagios_cfg, "w") as f:473 with open(nagios_cfg, "w") as f:
444 f.write(t.render(template_values))474 f.write(t.render(template_values))
445475
446 with open("hooks/templates/localhost_nagios2.cfg.tmpl", "r") as f:476 with open("hooks/templates/localhost_nagios2.cfg.tmpl", "r") as f:
447 templateDef = f.read()477 template_def = f.read()
448478
449 t = Template(templateDef)479 t = Template(template_def)
450 with open("/etc/nagios3/conf.d/localhost_nagios2.cfg", "w") as f:480 with open("/etc/nagios3/conf.d/localhost_nagios2.cfg", "w") as f:
451 f.write(t.render(template_values))481 f.write(t.render(template_values))
452482
@@ -456,9 +486,9 @@ def update_config():
456def update_cgi_config():486def update_cgi_config():
457 template_values = {"nagiosadmin": nagiosadmin, "ro_password": ro_password}487 template_values = {"nagiosadmin": nagiosadmin, "ro_password": ro_password}
458 with open("hooks/templates/nagios-cgi.tmpl", "r") as f:488 with open("hooks/templates/nagios-cgi.tmpl", "r") as f:
459 templateDef = f.read()489 template_def = f.read()
460490
461 t = Template(templateDef)491 t = Template(template_def)
462 with open(nagios_cgi_cfg, "w") as f:492 with open(nagios_cgi_cfg, "w") as f:
463 f.write(t.render(template_values))493 f.write(t.render(template_values))
464494
@@ -472,12 +502,12 @@ def update_cgi_config():
472# note: i tried to use cheetah, and it barfed, several times. It can go play502# note: i tried to use cheetah, and it barfed, several times. It can go play
473# in a fire. I'm jusing jinja2.503# in a fire. I'm jusing jinja2.
474def update_apache():504def update_apache():
475 """505 """Add SSL keys to default-ssl config.
506
476 Nagios3 is deployed as a global apache application from the archive.507 Nagios3 is deployed as a global apache application from the archive.
477 We'll get a little funky and add the SSL keys to the default-ssl config508 We'll get a little funky and add the SSL keys to the default-ssl config
478 which sets our keys, including the self-signed ones, as the host keyfiles.509 which sets our keys, including the self-signed ones, as the host keyfiles.
479 """510 """
480
481 # Start by Setting the ports.conf511 # Start by Setting the ports.conf
482512
483 with open("hooks/templates/ports-cfg.jinja2", "r") as f:513 with open("hooks/templates/ports-cfg.jinja2", "r") as f:
@@ -489,6 +519,7 @@ def update_apache():
489 f.write(t.render({"enable_http": HTTP_ENABLED}))519 f.write(t.render({"enable_http": HTTP_ENABLED}))
490520
491 # Next setup the default-ssl.conf521 # Next setup the default-ssl.conf
522
492 if os.path.exists(chain_file) and os.path.getsize(chain_file) > 0:523 if os.path.exists(chain_file) and os.path.getsize(chain_file) > 0:
493 ssl_chain = chain_file524 ssl_chain = chain_file
494 else:525 else:
@@ -515,6 +546,7 @@ def update_apache():
515 # Configure the behavior of http sites546 # Configure the behavior of http sites
516 sites = glob.glob("/etc/apache2/sites-available/*.conf")547 sites = glob.glob("/etc/apache2/sites-available/*.conf")
517 non_ssl = set(sites) - {ssl_conf}548 non_ssl = set(sites) - {ssl_conf}
549
518 for each in non_ssl:550 for each in non_ssl:
519 site = os.path.basename(each).rsplit(".", 1)[0]551 site = os.path.basename(each).rsplit(".", 1)[0]
520 Apache2Site(site).action(enabled=HTTP_ENABLED)552 Apache2Site(site).action(enabled=HTTP_ENABLED)
@@ -549,6 +581,7 @@ class Apache2Site:
549 def _enable(self):581 def _enable(self):
550 hookenv.log("Apache2Site: Enabling %s..." % self.site, "INFO")582 hookenv.log("Apache2Site: Enabling %s..." % self.site, "INFO")
551 self._call(["a2ensite", self.site])583 self._call(["a2ensite", self.site])
584
552 if self.port == 443:585 if self.port == 443:
553 self._call(["a2enmod", "ssl"])586 self._call(["a2enmod", "ssl"])
554 hookenv.open_port(self.port)587 hookenv.open_port(self.port)
@@ -562,6 +595,7 @@ class Apache2Site:
562def update_password(account, password):595def update_password(account, password):
563 """Update the charm and Apache's record of the password for the supplied account."""596 """Update the charm and Apache's record of the password for the supplied account."""
564 account_file = "".join(["/var/lib/juju/nagios.", account, ".passwd"])597 account_file = "".join(["/var/lib/juju/nagios.", account, ".passwd"])
598
565 if password:599 if password:
566 with open(account_file, "w") as f:600 with open(account_file, "w") as f:
567 f.write(password)601 f.write(password)
@@ -580,6 +614,7 @@ write_extra_config()
580# enable_traps_config and enable_pagerduty_config modify forced_contactgroup_members614# enable_traps_config and enable_pagerduty_config modify forced_contactgroup_members
581# they need to run before update_contacts that will consume that global var.615# they need to run before update_contacts that will consume that global var.
582enable_traps_config()616enable_traps_config()
617
583if ssl_configured():618if ssl_configured():
584 enable_ssl()619 enable_ssl()
585enable_pagerduty_config()620enable_pagerduty_config()
@@ -591,8 +626,10 @@ update_localhost()
591update_cgi_config()626update_cgi_config()
592update_contacts()627update_contacts()
593update_password("nagiosro", ro_password)628update_password("nagiosro", ro_password)
629
594if password:630if password:
595 update_password(nagiosadmin, password)631 update_password(nagiosadmin, password)
632
596if nagiosadmin != "nagiosadmin":633if nagiosadmin != "nagiosadmin":
597 update_password("nagiosadmin", False)634 update_password("nagiosadmin", False)
598635
diff --git a/hooks/website_relation_joined.py b/hooks/website_relation_joined.py
index 706a561..126e7cd 100755
--- a/hooks/website_relation_joined.py
+++ b/hooks/website_relation_joined.py
@@ -15,18 +15,15 @@
15# You should have received a copy of the GNU General Public License15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.16# along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
18import common18from charmhelpers.core.hookenv import config, log, relation_set
1919
20from charmhelpers.core.hookenv import (20import common
21 config,
22 log,
23 relation_set,
24)
2521
2622
27def main():23def main():
28 relation_data = {"hostname": common.get_local_ingress_address()}24 relation_data = {"hostname": common.get_local_ingress_address()}
29 sslcfg = config()["ssl"]25 sslcfg = config()["ssl"]
26
30 if sslcfg == "only":27 if sslcfg == "only":
31 relation_data["port"] = 44328 relation_data["port"] = 443
32 else:29 else:
diff --git a/tests/functional/conftest.py b/tests/functional/conftest.py
index a31034c..7ab5b1a 100644
--- a/tests/functional/conftest.py
+++ b/tests/functional/conftest.py
@@ -42,9 +42,11 @@ async def model(controller):
42 model = await controller.add_model(model_name)42 model = await controller.add_model(model_name)
43 yield model43 yield model
44 await model.disconnect()44 await model.disconnect()
45
45 if os.getenv("PYTEST_KEEP_MODEL"):46 if os.getenv("PYTEST_KEEP_MODEL"):
46 return47 return
47 await controller.destroy_model(model_name)48 await controller.destroy_model(model_name)
49
48 while model_name in await controller.list_models():50 while model_name in await controller.list_models():
49 await asyncio.sleep(1)51 await asyncio.sleep(1)
5052
@@ -60,7 +62,7 @@ async def current_model():
6062
61@pytest.fixture63@pytest.fixture
62async def get_app(model):64async def get_app(model):
63 """Return the application requested."""65 """Return the application requested.""" # noqa D202
6466
65 async def _get_app(name):67 async def _get_app(name):
66 try:68 try:
@@ -73,11 +75,12 @@ async def get_app(model):
7375
74@pytest.fixture76@pytest.fixture
75async def get_unit(model):77async def get_unit(model):
76 """Return the requested <app_name>/<unit_number> unit."""78 """Return the requested <app_name>/<unit_number> unit.""" # noqa D202
7779
78 async def _get_unit(name):80 async def _get_unit(name):
79 try:81 try:
80 (app_name, unit_number) = name.split("/")82 (app_name, unit_number) = name.split("/")
83
81 return model.applications[app_name].units[unit_number]84 return model.applications[app_name].units[unit_number]
82 except (KeyError, ValueError):85 except (KeyError, ValueError):
83 raise JujuError("Cannot find unit {}".format(name))86 raise JujuError("Cannot find unit {}".format(name))
@@ -87,7 +90,7 @@ async def get_unit(model):
8790
88@pytest.fixture91@pytest.fixture
89async def get_entity(model, get_unit, get_app):92async def get_entity(model, get_unit, get_app):
90 """Return a unit or an application."""93 """Return a unit or an application.""" # noqa D202
9194
92 async def _get_entity(name):95 async def _get_entity(name):
93 try:96 try:
@@ -103,7 +106,7 @@ async def get_entity(model, get_unit, get_app):
103106
104@pytest.fixture107@pytest.fixture
105async def run_command(get_unit):108async def run_command(get_unit):
106 """Run a command on a unit."""109 """Run a command on a unit.""" # noqa D202
107110
108 async def _run_command(cmd, target):111 async def _run_command(cmd, target):
109 """112 """
@@ -114,6 +117,7 @@ async def run_command(get_unit):
114 """117 """
115 unit = target if type(target) is juju.unit.Unit else await get_unit(target)118 unit = target if type(target) is juju.unit.Unit else await get_unit(target)
116 action = await unit.run(cmd)119 action = await unit.run(cmd)
120
117 return action.results121 return action.results
118122
119 return _run_command123 return _run_command
@@ -121,16 +125,16 @@ async def run_command(get_unit):
121125
122@pytest.fixture126@pytest.fixture
123async def file_stat(run_command):127async def file_stat(run_command):
124 """128 """Run stat on a file.
125 Run stat on a file.
126129
127 :param path: File path130 :param path: File path
128 :param target: Unit object or unit name string131 :param target: Unit object or unit name string
129 """132 """ # noqa D202
130133
131 async def _file_stat(path, target):134 async def _file_stat(path, target):
132 cmd = STAT_FILE % path135 cmd = STAT_FILE % path
133 results = await run_command(cmd, target)136 results = await run_command(cmd, target)
137
134 return json.loads(results["Stdout"])138 return json.loads(results["Stdout"])
135139
136 return _file_stat140 return _file_stat
@@ -138,16 +142,17 @@ async def file_stat(run_command):
138142
139@pytest.fixture143@pytest.fixture
140async def file_contents(run_command):144async def file_contents(run_command):
141 """Return the contents of a file."""145 """Return the contents of a file.""" # noqa D202
142146
143 async def _file_contents(path, target):147 async def _file_contents(path, target):
144 """Return the contents of a file.148 """Return the contents of a file.
145149
146 :param path: File path150 :param path: File path
147 :param target: Unit object or unit name string151 :param target: Unit object or unit name string
148 """152 """
149 cmd = "cat {}".format(path)153 cmd = "cat {}".format(path)
150 results = await run_command(cmd, target)154 results = await run_command(cmd, target)
155
151 return results["Stdout"]156 return results["Stdout"]
152157
153 return _file_contents158 return _file_contents
@@ -155,7 +160,7 @@ async def file_contents(run_command):
155160
156@pytest.fixture161@pytest.fixture
157async def reconfigure_app(get_app, model):162async def reconfigure_app(get_app, model):
158 """Apply a different config to the requested app."""163 """Apply a different config to the requested app.""" # noqa D202
159164
160 async def _reconfigure_app(cfg, target):165 async def _reconfigure_app(cfg, target):
161 application = (166 application = (
@@ -172,7 +177,7 @@ async def reconfigure_app(get_app, model):
172177
173@pytest.fixture178@pytest.fixture
174async def create_group(run_command):179async def create_group(run_command):
175 """Create the UNIX group specified."""180 """Create the UNIX group specified.""" # noqa D202
176181
177 async def _create_group(group_name, target):182 async def _create_group(group_name, target):
178 cmd = "sudo groupadd %s" % group_name183 cmd = "sudo groupadd %s" % group_name
@@ -185,11 +190,7 @@ pytestmark = pytest.mark.asyncio
185190
186CHARM_BUILD_DIR = os.getenv("CHARM_BUILD_DIR", "..").rstrip("/")191CHARM_BUILD_DIR = os.getenv("CHARM_BUILD_DIR", "..").rstrip("/")
187192
188SERIES = [193SERIES = ["trusty", "xenial", "bionic"]
189 "trusty",
190 "xenial",
191 "bionic",
192]
193194
194195
195############196############
@@ -210,6 +211,7 @@ async def relatives(model, series):
210 )211 )
211212
212 mysql = "mysql"213 mysql = "mysql"
214
213 if series != "trusty":215 if series != "trusty":
214 mysql = "percona-cluster"216 mysql = "percona-cluster"
215217
@@ -224,7 +226,7 @@ async def relatives(model, series):
224 )226 )
225 await model.block_until(227 await model.block_until(
226 lambda: mysql_app.units[0].workload_status == "active"228 lambda: mysql_app.units[0].workload_status == "active"
227 and mysql_app.units[0].agent_status == "idle"229 and mysql_app.units[0].agent_status == "idle" # noqa W503
228 )230 )
229231
230 yield {232 yield {
@@ -256,10 +258,11 @@ async def deploy_app(relatives, model, series):
256 )258 )
257 await model.block_until(259 await model.block_until(
258 lambda: nagios_app.units[0].agent_status == "idle"260 lambda: nagios_app.units[0].agent_status == "idle"
259 and relatives["mysql"]["app"].units[0].agent_status == "idle"261 and relatives["mysql"]["app"].units[0].agent_status == "idle" # noqa W503
260 )262 )
261263
262 yield nagios_app264 yield nagios_app
265
263 if os.getenv("PYTEST_KEEP_MODEL"):266 if os.getenv("PYTEST_KEEP_MODEL"):
264 return267 return
265268
@@ -277,6 +280,7 @@ class Agent:
277280
278 def is_active(self, status):281 def is_active(self, status):
279 u = self.u282 u = self.u
283
280 return u.agent_status == status and u.workload_status == "active"284 return u.agent_status == status and u.workload_status == "active"
281285
282 async def block_until_or_timeout(self, lambda_f, **kwargs):286 async def block_until_or_timeout(self, lambda_f, **kwargs):
@@ -299,6 +303,7 @@ async def unit(model, deploy_app):
299 """Return the unit we've deployed."""303 """Return the unit we've deployed."""
300 unit = Agent(deploy_app.units[0], deploy_app)304 unit = Agent(deploy_app.units[0], deploy_app)
301 await unit.block_until(lambda: unit.is_active("idle"))305 await unit.block_until(lambda: unit.is_active("idle"))
306
302 return unit307 return unit
303308
304309
@@ -306,4 +311,5 @@ async def unit(model, deploy_app):
306async def auth(file_contents, unit):311async def auth(file_contents, unit):
307 """Return the basic auth credentials."""312 """Return the basic auth credentials."""
308 nagiospwd = await file_contents("/var/lib/juju/nagios.passwd", unit.u)313 nagiospwd = await file_contents("/var/lib/juju/nagios.passwd", unit.u)
314
309 return "nagiosadmin", nagiospwd.strip()315 return "nagiosadmin", nagiospwd.strip()
diff --git a/tests/functional/test_config.py b/tests/functional/test_config.py
index 1b9310a..6bc36a6 100644
--- a/tests/functional/test_config.py
+++ b/tests/functional/test_config.py
@@ -1,5 +1,7 @@
1from async_generator import asynccontextmanager1from async_generator import asynccontextmanager
2
2import pytest3import pytest
4
3import requests5import requests
46
5pytestmark = pytest.mark.asyncio7pytestmark = pytest.mark.asyncio
@@ -18,8 +20,7 @@ async def config(unit, item, test_value, post_test):
1820
19@pytest.fixture(params=["on", "only"])21@pytest.fixture(params=["on", "only"])
20async def ssl(unit, request):22async def ssl(unit, request):
21 """23 """Enable SSL before a test, then disable after test.
22 Enable SSL before a test, then disable after test
2324
24 :param Agent unit: unit from the fixture25 :param Agent unit: unit from the fixture
25 :param request: test parameters26 :param request: test parameters
@@ -30,8 +31,7 @@ async def ssl(unit, request):
3031
31@pytest.fixture32@pytest.fixture
32async def extra_config(unit):33async def extra_config(unit):
33 """34 """Enable extraconfig for a test, and revert afterwards.
34 Enable extraconfig for a test, and revert afterwards
3535
36 :param Agent unit: unit from the fixture36 :param Agent unit: unit from the fixture
37 """37 """
@@ -48,8 +48,7 @@ async def extra_config(unit):
4848
49@pytest.fixture49@pytest.fixture
50async def livestatus_path(unit):50async def livestatus_path(unit):
51 """51 """Enable livestatus before a test, then disable after test.
52 Enable livestatus before a test, then disable after test
5352
54 :param Agent unit: unit from the fixture53 :param Agent unit: unit from the fixture
55 """54 """
@@ -60,8 +59,7 @@ async def livestatus_path(unit):
6059
61@pytest.fixture()60@pytest.fixture()
62async def enable_pagerduty(unit):61async def enable_pagerduty(unit):
63 """62 """Enable enable_pagerduty before first test, then disable after last test.
64 Enable enable_pagerduty before first test, then disable after last test
6563
66 :param Agent unit: unit from the fixture64 :param Agent unit: unit from the fixture
67 """65 """
diff --git a/tests/functional/test_deploy.py b/tests/functional/test_deploy.py
index 32503c2..efbafb7 100644
--- a/tests/functional/test_deploy.py
+++ b/tests/functional/test_deploy.py
@@ -1,4 +1,5 @@
1import pytest1import pytest
2
2import requests3import requests
34
4pytestmark = pytest.mark.asyncio5pytestmark = pytest.mark.asyncio
diff --git a/tests/unit/test_website_relation_joined.py b/tests/unit/test_website_relation_joined.py
index b4ca91a..7dff088 100644
--- a/tests/unit/test_website_relation_joined.py
+++ b/tests/unit/test_website_relation_joined.py
@@ -1,6 +1,7 @@
1import unittest.mock as mock1import unittest.mock as mock
22
3import pytest3import pytest
4
4import website_relation_joined5import website_relation_joined
56
67
diff --git a/tox.ini b/tox.ini
index 8f1b11b..17cb36f 100644
--- a/tox.ini
+++ b/tox.ini
@@ -48,33 +48,7 @@ ignore = # TODO remove most of these
48 D101,48 D101,
49 D102,49 D102,
50 D103,50 D103,
51 D104,
52 D107,51 D107,
53 D202,
54 D205,
55 D208,
56 D210,
57 D400,
58 D401,
59 I100,
60 I101,
61 I201,
62 I202,
63 E201,
64 E202,
65 E231,
66 E121,
67 E126,
68 E131,
69 D201,
70 E302,
71 E501,
72 N806,
73 N816,
74 W503,
75 W504
76
77
78max-line-length = 8852max-line-length = 88
79max-complexity = 1053max-complexity = 10
8054

Subscribers

People subscribed via source and target branches