Merge ~xavpaice/charm-grafana:bug/1873105 into charm-grafana:master

Proposed by Xav Paice
Status: Merged
Approved by: Joe Guo
Approved revision: 59f8c55d0d5cca497a0b8d7b64128cdf288ab883
Merged at revision: 2078b8c32cf6c26b0ad3e4444b69cf553039757c
Proposed branch: ~xavpaice/charm-grafana:bug/1873105
Merge into: charm-grafana:master
Diff against target: 517 lines (+86/-113)
8 files modified
.gitignore (+1/-0)
Makefile (+1/-1)
lib/charms/layer/grafana.py (+3/-8)
reactive/grafana.py (+38/-66)
tests/functional/tests/test_grafana.py (+10/-30)
tests/unit/requirements.txt (+3/-0)
tests/unit/test_grafana.py (+27/-4)
tox.ini (+3/-4)
Reviewer Review Type Date Requested Status
Joe Guo (community) Approve
Paul Goins Approve
Xav Paice (community) Needs Resubmitting
Alvaro Uria Pending
Peter Sabaini Pending
Review via email: mp+388019@code.launchpad.net

This proposal supersedes a proposal from 2020-04-16.

Commit message

Replace the process monitoring with functional

To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : Posted in a previous version of this proposal

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
Peter Sabaini (peter-sabaini) wrote : Posted in a previous version of this proposal

Two minor comments inline, otherwise lgtm, cheers

review: Approve
Revision history for this message
Alvaro Uria (aluria) wrote : Posted in a previous version of this proposal

Hi, there are a few things to be reviewed:
* Makefile does not have a unittest target (probably because unit tests didn't exist). However, tox.ini does have a "unit" env. I think the Makefile misses the target, running "tox -e unit"

* Functional tests miss nagios-{{series}} and nrpe-{{series}} in the overlay.yaml.j2 template. It would be good to test when grafana gets related to nrpe, by checking that the check_grafana_http.cfg file exists in /etc/nagios/nrpe.d. There are examples of such check (file_stat) in ie. charm-openstack-service-checks

* Functional tests don't test a deployment of cs:grafana + juju upgrade-charm to the local version. I spotted a bug that can be seen at [1]. "nrpe-external-master.available" state gets removed and wipe_nrpe_checks is called. Looking at the debug lines, the http interface checks endpoint.website.joined state and removes website.available. I don't see any trace of calling the nrpe-external-master interface and do a similar thing (which OTOH only occurs when n-e-m-relation-{departed,broken} hooks are triggered - and debug lines don't show such run).

On this 3rd test (upgrade-charm) it would be could to verify that the old checks (check_grafana-server.cfg [apt] or check_snap.grafana.grafana.cfg [snap]) are removed (backward compatibility with a previous deployed environment). On fresh deploys, such checks won't exist, only check_grafana_http.cfg.

1. https://pastebin.ubuntu.com/p/2smQt4X3Wd/

review: Needs Fixing
Revision history for this message
Alvaro Uria (aluria) wrote : Posted in a previous version of this proposal

BTW, when I tried to workaround the issue, by manually setting the nrpe-external-master.available flag, I got this error [1].

1. https://pastebin.ubuntu.com/p/Fj5zzRJt2C/

Revision history for this message
Xav Paice (xavpaice) wrote : Posted in a previous version of this proposal

Change needs a rebase, and rework to the tests. WIP.

Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
Joe Guo (guoqiao) wrote :

made 2 trivial comments inline.

Revision history for this message
Paul Goins (vultaire) wrote :

Replying to previous comments:

* Re: unit tests: presently "make unittest" calls "tox -e unit"; this may be because of the rebase that it does work now. That being said, the unit tests fail; one of them needs to be repaired.

* Re: functional tests:

  i. NRPE-related tests exist; I'm guessing this is due to the rebase.
  ii. I still don't see any upgrade-charm-related tests. I haven't reviewed the sources about whether the bug in question exists in the current version, but this could be considered a gap.
  iii. Uncertain re: check_grafana-server.cfg and check_snap.grafana.grafana.cfg; are these issues?

At a minimum, I think the unit tests should be fixed. I'm not 100% sure whether the upgrade-charm tests should be addressed now or perhaps after the next charm series release.

review: Needs Fixing
Revision history for this message
Xav Paice (xavpaice) wrote :

Unit tests fixed, plus one or to minor lints.

"ii. I still don't see any upgrade-charm-related tests. I haven't reviewed the sources about whether the bug in question exists in the current version, but this could be considered a gap."

Testing for upgrade-charm is way out of scope for this change, we don't run that test for a single one of the LMA charm stack right now - though it would be an excellent addition and make life a heck of a lot easier during the release process. I don't think we can reasonably block this change because of something so far out of scope.

review: Needs Resubmitting
Revision history for this message
Paul Goins (vultaire) wrote :

LGTM (and agreed with scope sentiment)

review: Approve
Revision history for this message
Xav Paice (xavpaice) wrote :

info: When running lint on this, Black wants to change a number of items, but I've not included that linting in this change since we're going to do a separate commit for lint changes.

Revision history for this message
Joe Guo (guoqiao) wrote :

LGTM, +1.

review: Approve
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Change successfully merged at revision 2078b8c32cf6c26b0ad3e4444b69cf553039757c

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/.gitignore b/.gitignore
index 32e2995..34da750 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,4 @@ repo-info
2020
21# reports21# reports
22report/*22report/*
23.unit-state.db
diff --git a/Makefile b/Makefile
index 60f593c..1334496 100644
--- a/Makefile
+++ b/Makefile
@@ -21,7 +21,7 @@ lint:
21 @echo "Running flake8"21 @echo "Running flake8"
22 @tox -e lint22 @tox -e lint
2323
24test: lint24unittest:
25 @echo "Running unit tests..."25 @echo "Running unit tests..."
26 @tox -e unit26 @tox -e unit
2727
diff --git a/lib/charms/layer/grafana.py b/lib/charms/layer/grafana.py
index 9853dc2..cb7fd2c 100644
--- a/lib/charms/layer/grafana.py
+++ b/lib/charms/layer/grafana.py
@@ -32,9 +32,7 @@ SNAP_CODENAME_MAP = {
3232
33def get_admin_password():33def get_admin_password():
34 """Get admin password from config, fall back to kv."""34 """Get admin password from config, fall back to kv."""
35 return config("admin_password") or unitdata.kv().get(35 return config("admin_password") or unitdata.kv().get("grafana.admin_password")
36 "grafana.admin_password"
37 )
3836
3937
40def import_dashboard(dashboard, name=None):38def import_dashboard(dashboard, name=None):
@@ -132,9 +130,7 @@ def check_snap_channel(snap_name, channel):
132 UNCHANGED: Channel unchanged130 UNCHANGED: Channel unchanged
133 DOWNGRADE: Would result in downgrade of major version131 DOWNGRADE: Would result in downgrade of major version
134 """132 """
135 installed_ver = parse_snap_major_version(133 installed_ver = parse_snap_major_version(snap.get_installed_channel(snap_name))
136 snap.get_installed_channel(snap_name)
137 )
138 new_ver = parse_snap_major_version(channel)134 new_ver = parse_snap_major_version(channel)
139 is_refresh_available = snap.is_refresh_available(snap_name)135 is_refresh_available = snap.is_refresh_available(snap_name)
140 if new_ver == -2:136 if new_ver == -2:
@@ -163,8 +159,7 @@ def check_snap_channel(snap_name, channel):
163 return ChangeStatus.UNCHANGED159 return ChangeStatus.UNCHANGED
164 if installed_ver < new_ver:160 if installed_ver < new_ver:
165 msg = (161 msg = (
166 "PACKAGE UPGRADE REQUIRES MANUAL INTERVENTION: see {} for "162 "PACKAGE UPGRADE REQUIRES MANUAL INTERVENTION: see {} for more info"
167 "more info"
168 ).format(VERSION_CHANGE_URL)163 ).format(VERSION_CHANGE_URL)
169 status_set("blocked", msg)164 status_set("blocked", msg)
170 log(msg)165 log(msg)
diff --git a/reactive/grafana.py b/reactive/grafana.py
index 17dfad1..4434b17 100644
--- a/reactive/grafana.py
+++ b/reactive/grafana.py
@@ -97,6 +97,7 @@ from charms.reactive import (
97 remove_state,97 remove_state,
98 set_state,98 set_state,
99 when,99 when,
100 when_any,
100 when_not,101 when_not,
101)102)
102from charms.reactive.helpers import (103from charms.reactive.helpers import (
@@ -184,8 +185,7 @@ def install_packages():
184185
185 if config.changed("install_file") and config.get("install_file"):186 if config.changed("install_file") and config.get("install_file"):
186 hookenv.status_set(187 hookenv.status_set(
187 "maintenance",188 "maintenance", "Installing deb pkgs since install_file changed",
188 "Installing deb pkgs since install_file changed",
189 )189 )
190190
191 url = config.get("install_file")191 url = config.get("install_file")
@@ -249,9 +249,7 @@ def install_plugins():
249249
250 if os.path.exists(plugins_dir):250 if os.path.exists(plugins_dir):
251 hookenv.log("Cleaning up currently installed plugins")251 hookenv.log("Cleaning up currently installed plugins")
252 hookenv.status_set(252 hookenv.status_set("maintenance", "Cleaning up currently installed plugins")
253 "maintenance", "Cleaning up currently installed plugins"
254 )
255 for entry in os.listdir(plugins_dir):253 for entry in os.listdir(plugins_dir):
256 entry_path = os.path.join(plugins_dir, entry)254 entry_path = os.path.join(plugins_dir, entry)
257 if os.path.isfile(entry_path):255 if os.path.isfile(entry_path):
@@ -283,12 +281,12 @@ def install_plugins():
283@when_not("grafana.change-block")281@when_not("grafana.change-block")
284def upgrade_charm():282def upgrade_charm():
285 hookenv.status_set(283 hookenv.status_set(
286 "maintenance",284 "maintenance", "Forcing package update and reconfiguration on upgrade-charm",
287 "Forcing package update and reconfiguration on upgrade-charm",
288 )285 )
289 remove_state("grafana.installed")286 remove_state("grafana.installed")
290 remove_state("grafana.backup.configured")287 remove_state("grafana.backup.configured")
291 remove_state("grafana.configured")288 remove_state("grafana.configured")
289 remove_state("grafana.nagios-setup.completed")
292290
293291
294@hook("config-changed")292@hook("config-changed")
@@ -314,9 +312,7 @@ def config_changed():
314 else:312 else:
315 # Install from requested channel313 # Install from requested channel
316 snap.install(314 snap.install(
317 SNAP_NAME,315 SNAP_NAME, channel=config["snap_channel"], force_dangerous=False,
318 channel=config["snap_channel"],
319 force_dangerous=False,
320 )316 )
321 remove_state("grafana.configured")317 remove_state("grafana.configured")
322 if config.changed("dashboards_backup_schedule") or config.changed(318 if config.changed("dashboards_backup_schedule") or config.changed(
@@ -327,6 +323,7 @@ def config_changed():
327 remove_state("grafana.admin_password.set")323 remove_state("grafana.admin_password.set")
328 if config.changed("install_file") and config.get("install_file"):324 if config.changed("install_file") and config.get("install_file"):
329 remove_state("grafana.installed")325 remove_state("grafana.installed")
326 remove_state("grafana.nagios-setup.completed")
330327
331328
332def check_ports(new_port):329def check_ports(new_port):
@@ -401,15 +398,11 @@ def add_backup_api_keys():
401 "SELECT id FROM api_key WHERE org_id=? AND name=?", [org_id, name],398 "SELECT id FROM api_key WHERE org_id=? AND name=?", [org_id, name],
402 ):399 ):
403 hookenv.log(400 hookenv.log(
404 "API key {} in org {} already exists, skipping".format(401 "API key {} in org {} already exists, skipping".format(name, org_id)
405 name, org_id
406 )
407 )402 )
408 continue403 continue
409 j = {"n": name, "k": passwd, "id": org_id}404 j = {"n": name, "k": passwd, "id": org_id}
410 encoded = base64.b64encode(json.dumps(j).encode("ascii")).decode(405 encoded = base64.b64encode(json.dumps(j).encode("ascii")).decode("ascii")
411 "ascii"
412 )
413 stmt = (406 stmt = (
414 "INSERT INTO api_key (org_id, name, key, role, created, updated)"407 "INSERT INTO api_key (org_id, name, key, role, created, updated)"
415 + ' VALUES (?,?,?,"Viewer",?,?)'408 + ' VALUES (?,?,?,"Viewer",?,?)'
@@ -473,9 +466,7 @@ def setup_backup_shedule():
473466
474 config = hookenv.config()467 config = hookenv.config()
475 if config.get("dashboards_backup_schedule", False):468 if config.get("dashboards_backup_schedule", False):
476 hookenv.status_set(469 hookenv.status_set("maintenance", "Configuring grafana dashboard backup")
477 "maintenance", "Configuring grafana dashboard backup"
478 )
479 hookenv.log("Setting up dashboards backup job...")470 hookenv.log("Setting up dashboards backup job...")
480 host.rsync(471 host.rsync(
481 "files/dashboards_backup", "/usr/local/bin/dashboards_backup",472 "files/dashboards_backup", "/usr/local/bin/dashboards_backup",
@@ -494,9 +485,7 @@ def setup_backup_shedule():
494 group="root",485 group="root",
495 perms=0o640,486 perms=0o640,
496 )487 )
497 hookenv.status_set(488 hookenv.status_set("active", "Completed configuring grafana dashboard backup")
498 "active", "Completed configuring grafana dashboard backup"
499 )
500 set_state("grafana.backup.configured")489 set_state("grafana.backup.configured")
501490
502491
@@ -518,9 +507,7 @@ def restart_grafana():
518 hookenv.status_set("maintenance", msg)507 hookenv.status_set("maintenance", msg)
519 hookenv.log(msg)508 hookenv.log(msg)
520 host.service_start(svcname)509 host.service_start(svcname)
521 elif any_file_changed([grafana_ini]) or is_state(510 elif any_file_changed([grafana_ini]) or is_state("config.changed.install_plugins"):
522 "config.changed.install_plugins"
523 ):
524 msg = "Restarting {}".format(svcname)511 msg = "Restarting {}".format(svcname)
525 hookenv.log(msg)512 hookenv.log(msg)
526 hookenv.status_set("maintenance", msg)513 hookenv.status_set("maintenance", msg)
@@ -531,30 +518,33 @@ def restart_grafana():
531518
532519
533@when("grafana.started")520@when("grafana.started")
534@when("nrpe-external-master.available")521@when_any("nrpe-external-master.available", "nrpe-external-master.connected")
535@when_not("grafana.change-block")522@when_not("grafana.change-block")
536def update_nrpe_config(svc):523@when_not("grafana.nagios-setup.completed")
537 kv = unitdata.kv()524def update_nrpe_config():
538 source = kv.get("install_method")
539 if source in ("snap", "apt"):
540 svcname = SVCNAME[source]
541 else:
542 hookenv.status_set("blocked", "Unsupported install_method")
543 return
544 # python-dbus is used by check_upstart_job525 # python-dbus is used by check_upstart_job
545 fetch.apt_install("python-dbus", fatal=True)526 fetch.apt_install("python-dbus", fatal=True)
546 hostname = nrpe.get_nagios_hostname()527 hostname = nrpe.get_nagios_hostname()
547 current_unit = nrpe.get_nagios_unit_name()
548 nrpe_setup = nrpe.NRPE(hostname=hostname)528 nrpe_setup = nrpe.NRPE(hostname=hostname)
549 nrpe.add_init_service_checks(nrpe_setup, [svcname], current_unit)529 config = hookenv.config()
530
531 # write the http check
532 nrpe_setup.add_check(
533 "grafana_http",
534 "Grafana HTTP check",
535 "check_http -I 127.0.0.1 -p {} -u /login".format(config["port"]),
536 )
550 nrpe_setup.write()537 nrpe_setup.write()
538 set_state("grafana.nagios-setup.completed")
551539
552540
553@when_not("nrpe-external-master.available")541@when_not("nrpe-external-master.connected")
554def wipe_nrpe_checks():542def wipe_nrpe_checks():
555 checks = [543 checks = [
556 "/etc/nagios/nrpe.d/check_grafana-server.cfg",544 "/etc/nagios/nrpe.d/check_grafana-server.cfg",
557 "/etc/nagios/nrpe.d/check_grafana.cfg",545 "/etc/nagios/nrpe.d/check_grafana.cfg",
546 "/etc/nagios/nrpe.d/check_grafana_http.cfg",
547 "/etc/nagios/nrpe.d/check_snap.grafana.grafana.cfg",
558 "/var/lib/nagios/export/service__*_grafana-server.cfg",548 "/var/lib/nagios/export/service__*_grafana-server.cfg",
559 "/var/lib/nagios/export/service__*_grafana.cfg",549 "/var/lib/nagios/export/service__*_grafana.cfg",
560 ]550 ]
@@ -562,6 +552,7 @@ def wipe_nrpe_checks():
562 for f in glob.glob(check):552 for f in glob.glob(check):
563 if os.path.isfile(f):553 if os.path.isfile(f):
564 os.unlink(f)554 os.unlink(f)
555 remove_state("grafana.nagios-setup.completed")
565556
566557
567@when("grafana.started")558@when("grafana.started")
@@ -602,8 +593,7 @@ def sources_gone(relation):
602 conn = sqlite3.connect("{}/grafana.db".format(data_dir), timeout=30)593 conn = sqlite3.connect("{}/grafana.db".format(data_dir), timeout=30)
603 cur = conn.cursor()594 cur = conn.cursor()
604 cur.execute(595 cur.execute(
605 "DELETE FROM DATA_SOURCE WHERE type=? AND url=?",596 "DELETE FROM DATA_SOURCE WHERE type=? AND url=?", (ds["type"], ds["url"]),
606 (ds["type"], ds["url"]),
607 )597 )
608 conn.commit()598 conn.commit()
609 cur.close()599 cur.close()
@@ -668,16 +658,12 @@ def check_datasource(ds):
668 return658 return
669 conn = sqlite3.connect("{}/grafana.db".format(data_dir), timeout=30)659 conn = sqlite3.connect("{}/grafana.db".format(data_dir), timeout=30)
670 cur = conn.cursor()660 cur = conn.cursor()
671 query = cur.execute(661 query = cur.execute("SELECT id, type, name, url, is_default FROM DATA_SOURCE")
672 "SELECT id, type, name, url, is_default FROM DATA_SOURCE"
673 )
674 rows = query.fetchall()662 rows = query.fetchall()
675 ds_name = "{} - {}".format(ds["service_name"], ds["description"])663 ds_name = "{} - {}".format(ds["service_name"], ds["description"])
676 for row in rows:664 for row in rows:
677 if row[1] == ds["type"] and row[3] == ds["url"]:665 if row[1] == ds["type"] and row[3] == ds["url"]:
678 hookenv.log(666 hookenv.log("Datasource already exist, updating: {}".format(ds_name))
679 "Datasource already exist, updating: {}".format(ds_name)
680 )
681 stmt, values = generate_query(ds, row[4], id=row[0])667 stmt, values = generate_query(ds, row[4], id=row[0])
682 print(stmt, values)668 print(stmt, values)
683 cur.execute(stmt, values)669 cur.execute(stmt, values)
@@ -705,16 +691,12 @@ def render_custom(source, context, **parameters):
705 template_folder = os.path.join(691 template_folder = os.path.join(
706 hookenv.charm_dir(), "templates/dashboards/prometheus"692 hookenv.charm_dir(), "templates/dashboards/prometheus"
707 )693 )
708 environment = Environment(694 environment = Environment(loader=FileSystemLoader(template_folder), **parameters)
709 loader=FileSystemLoader(template_folder), **parameters
710 )
711 try:695 try:
712 template = environment.get_template(source)696 template = environment.get_template(source)
713 except exceptions.TemplateNotFound as e:697 except exceptions.TemplateNotFound as e:
714 hookenv.log(698 hookenv.log(
715 "Could not load template {} from {}".format(699 "Could not load template {} from {}".format(source, template_folder)
716 source, template_folder
717 )
718 )700 )
719 raise e701 raise e
720 return template.render(context)702 return template.render(context)
@@ -817,9 +799,7 @@ def check_and_add_dashboard(
817 dashboard_changed = diff(new, curr)799 dashboard_changed = diff(new, curr)
818 if not dashboard_changed:800 if not dashboard_changed:
819 hookenv.log(801 hookenv.log(
820 "Skipping Dashboard Template: already up to date: {}".format(802 "Skipping Dashboard Template: already up to date: {}".format(filename)
821 filename
822 )
823 )803 )
824 return804 return
825805
@@ -835,15 +815,11 @@ def check_and_add_dashboard(
835815
836 hookenv.log("Using Dashboard Template: {}".format(filename))816 hookenv.log("Using Dashboard Template: {}".format(filename))
837 post_req = "http://127.0.0.1:{}/api/dashboards/db".format(port)817 post_req = "http://127.0.0.1:{}/api/dashboards/db".format(port)
838 r = requests.post(818 r = requests.post(post_req, json=dashboard_json, auth=("admin", gf_adminpasswd))
839 post_req, json=dashboard_json, auth=("admin", gf_adminpasswd)
840 )
841819
842 if r.status_code != 200:820 if r.status_code != 200:
843 hookenv.log(821 hookenv.log(
844 "Posting template {} failed with error: {}".format(822 "Posting template {} failed with error: {}".format(filename, r.text),
845 filename, r.text
846 ),
847 hookenv.ERROR,823 hookenv.ERROR,
848 )824 )
849825
@@ -862,9 +838,7 @@ def generate_prometheus_dashboards(gf_adminpasswd, ds):
862 config = hookenv.config()838 config = hookenv.config()
863839
864 # https://prometheus.io/docs/prometheus/latest/querying/api/#querying-label-values840 # https://prometheus.io/docs/prometheus/latest/querying/api/#querying-label-values
865 response = requests.get(841 response = requests.get("{}/api/v1/label/__name__/values".format(ds["url"]))
866 "{}/api/v1/label/__name__/values".format(ds["url"])
867 )
868 if response.status_code != 200:842 if response.status_code != 200:
869 hookenv.log(843 hookenv.log(
870 "Could not reach prometheus API status code: "844 "Could not reach prometheus API status code: "
@@ -1105,9 +1079,7 @@ def check_adminuser():
1105 conn.commit()1079 conn.commit()
1106 hookenv.log("[*] admin password updated on database")1080 hookenv.log("[*] admin password updated on database")
1107 else:1081 else:
1108 hookenv.log(1082 hookenv.log("Could not update user table: hpwgen func failed")
1109 "Could not update user table: hpwgen func failed"
1110 )
1111 break1083 break
1112 conn.close()1084 conn.close()
1113 except sqlite3.OperationalError as e:1085 except sqlite3.OperationalError as e:
diff --git a/tests/functional/tests/test_grafana.py b/tests/functional/tests/test_grafana.py
index 31d3b4d..06a1942 100644
--- a/tests/functional/tests/test_grafana.py
+++ b/tests/functional/tests/test_grafana.py
@@ -27,9 +27,7 @@ class BaseGrafanaTest(unittest.TestCase):
27 cls.lead_unit_name = model.get_lead_unit_name(27 cls.lead_unit_name = model.get_lead_unit_name(
28 cls.application_name, model_name=cls.model_name28 cls.application_name, model_name=cls.model_name
29 )29 )
30 cls.units = model.get_units(30 cls.units = model.get_units(cls.application_name, model_name=cls.model_name)
31 cls.application_name, model_name=cls.model_name
32 )
33 cls.grafana_ip = model.get_app_ips(cls.application_name)[0]31 cls.grafana_ip = model.get_app_ips(cls.application_name)[0]
3432
35 def get_unit_status(self, unit):33 def get_unit_status(self, unit):
@@ -84,9 +82,7 @@ class CharmOperationTest(BaseGrafanaTest):
84 We'll retry until the TEST_TIMEOUT.82 We'll retry until the TEST_TIMEOUT.
85 """83 """
86 test_command = "{} -I 127.0.0.1 -p {} -u {}".format(84 test_command = "{} -I 127.0.0.1 -p {} -u {}".format(
87 "/usr/lib/nagios/plugins/check_http",85 "/usr/lib/nagios/plugins/check_http", DEFAULT_API_PORT, DEFAULT_API_URL,
88 DEFAULT_API_PORT,
89 DEFAULT_API_URL,
90 )86 )
91 timeout = time.time() + TEST_TIMEOUT87 timeout = time.time() + TEST_TIMEOUT
92 while time.time() < timeout:88 while time.time() < timeout:
@@ -94,9 +90,7 @@ class CharmOperationTest(BaseGrafanaTest):
94 if response["Code"] == "0":90 if response["Code"] == "0":
95 return91 return
96 logging.warning(92 logging.warning(
97 "Unexpected check_http response: {}. Retrying in 30s.".format(93 "Unexpected check_http response: {}. Retrying in 30s.".format(response)
98 response
99 )
100 )94 )
101 time.sleep(30)95 time.sleep(30)
10296
@@ -104,9 +98,7 @@ class CharmOperationTest(BaseGrafanaTest):
104 self.fail(98 self.fail(
105 "http port didn't respond to the command \n"99 "http port didn't respond to the command \n"
106 "'{test_command}' as expected.\n"100 "'{test_command}' as expected.\n"
107 "Result: {result}".format(101 "Result: {result}".format(test_command=test_command, result=response)
108 test_command=test_command, result=response
109 )
110 )102 )
111103
112 def test_02_nrpe_http_check(self):104 def test_02_nrpe_http_check(self):
@@ -114,21 +106,11 @@ class CharmOperationTest(BaseGrafanaTest):
114 logging.debug(106 logging.debug(
115 "Verify the nrpe check is created and has the required content..."107 "Verify the nrpe check is created and has the required content..."
116 )108 )
117 # Check if this is snap or apt109 expected_nrpe_check = (
118 cmd = "config-get install_method"110 "command[check_grafana_http]=/usr/lib/nagios/plugins/check_http "
119 install_method = model.run_on_unit(self.lead_unit_name, cmd)111 "-I 127.0.0.1 -p 3000 -u /login"
120 if "apt" in install_method["Stdout"]:112 )
121 expected_nrpe_check = (113 cmd = "cat /etc/nagios/nrpe.d/check_grafana_http.cfg"
122 "command[check_grafana-server]=/usr/local/lib/nagios/"
123 "plugins/check_systemd.py grafana-server"
124 )
125 cmd = "cat /etc/nagios/nrpe.d/check_grafana-server.cfg"
126 else: # must be snap
127 expected_nrpe_check = (
128 "command[check_snap.grafana.grafana]=/usr/local/lib/"
129 "nagios/plugins/check_systemd.py snap.grafana.grafana"
130 )
131 cmd = "cat /etc/nagios/nrpe.d/check_snap.grafana.grafana.cfg"
132 result = model.run_on_unit(self.lead_unit_name, cmd)114 result = model.run_on_unit(self.lead_unit_name, cmd)
133 code = result.get("Code")115 code = result.get("Code")
134 if code != "0":116 if code != "0":
@@ -232,9 +214,7 @@ class SnappedGrafanaTest(BaseGrafanaTest):
232 model.block_until_unit_wl_status(self.lead_unit_name, "blocked")214 model.block_until_unit_wl_status(self.lead_unit_name, "blocked")
233 model.block_until_all_units_idle()215 model.block_until_all_units_idle()
234 status_message = self.get_unit_status(self.lead_unit_name)216 status_message = self.get_unit_status(self.lead_unit_name)
235 self.assertTrue(217 self.assertTrue("PACKAGE DOWNGRADES ARE NOT SUPPORTED" in status_message)
236 "PACKAGE DOWNGRADES ARE NOT SUPPORTED" in status_message
237 )
238 model.set_application_config( # unblock unit again218 model.set_application_config( # unblock unit again
239 self.application_name, {"snap_channel": "7/stable"}219 self.application_name, {"snap_channel": "7/stable"}
240 )220 )
diff --git a/tests/unit/requirements.txt b/tests/unit/requirements.txt
index 29f9318..cb975bd 100644
--- a/tests/unit/requirements.txt
+++ b/tests/unit/requirements.txt
@@ -4,3 +4,6 @@ mock
4pytest4pytest
5pytest-cov5pytest-cov
6requests6requests
7jsondiff
8pbkdf2
9pycrypto
diff --git a/tests/unit/test_grafana.py b/tests/unit/test_grafana.py
index 57e730d..0c8a658 100644
--- a/tests/unit/test_grafana.py
+++ b/tests/unit/test_grafana.py
@@ -1,18 +1,18 @@
1from os.path import isfile
2from unittest import mock
3import sys1import sys
4import unittest2import unittest
53from os.path import isfile
4from unittest import mock
5from unittest.mock import call
66
7sys.modules["charms.layer.snap"] = mock.Mock()7sys.modules["charms.layer.snap"] = mock.Mock()
88
9
10from charms.layer.grafana import ( # noqa E4029from charms.layer.grafana import ( # noqa E402
11 download_file,10 download_file,
12 get_cmd_output,11 get_cmd_output,
13 get_deb_package_version,12 get_deb_package_version,
14 get_installed_package_version,13 get_installed_package_version,
15)14)
15from reactive import grafana # noqa E402
1616
1717
18class GrafanaTestCase(unittest.TestCase):18class GrafanaTestCase(unittest.TestCase):
@@ -45,3 +45,26 @@ class GrafanaTestCase(unittest.TestCase):
45 self.assertTrue(isfile(path))45 self.assertTrue(isfile(path))
46 version = get_deb_package_version(path)46 version = get_deb_package_version(path)
47 self.assertEqual(version, "2.10-2")47 self.assertEqual(version, "2.10-2")
48
49 @mock.patch("charmhelpers.fetch.apt_install")
50 @mock.patch("charmhelpers.contrib.charmsupport.nrpe.NRPE")
51 @mock.patch("charmhelpers.contrib.charmsupport.nrpe.get_nagios_hostname")
52 @mock.patch("charmhelpers.core.hookenv.config")
53 def test_update_nrpe_config(
54 self, mock_hookenv_config, mock_get_nagios_hostname, mock_nrpe, *args
55 ):
56 sys.modules["charms.layer"] = mock.MagicMock()
57 sys.modules["charms.layer.grafana"] = mock.MagicMock()
58 mock_hookenv_config.return_value = {"port": 1234}
59 mock_get_nagios_hostname.return_value = "testunit"
60 grafana.update_nrpe_config()
61 calls = [
62 call(hostname="testunit"),
63 call().add_check(
64 "grafana_http",
65 "Grafana HTTP check",
66 "check_http -I 127.0.0.1 -p 1234 -u /login",
67 ),
68 call().write(),
69 ]
70 mock_nrpe.assert_has_calls(calls)
diff --git a/tox.ini b/tox.ini
index 486c489..c62ec88 100644
--- a/tox.ini
+++ b/tox.ini
@@ -6,7 +6,7 @@ skip_missing_interpreters = True
6[testenv]6[testenv]
7basepython = python37basepython = python3
8setenv =8setenv =
9 PYTHONPATH = .9 PYTHONPATH = .:lib
10passenv =10passenv =
11 HOME11 HOME
12 CHARM_BUILD_DIR12 CHARM_BUILD_DIR
@@ -24,7 +24,6 @@ commands = pytest -v --ignore {toxinidir}/tests/functional \
24 --cov-report=html:report/html24 --cov-report=html:report/html
25deps = -r{toxinidir}/tests/unit/requirements.txt25deps = -r{toxinidir}/tests/unit/requirements.txt
26 -r{toxinidir}/requirements.txt26 -r{toxinidir}/requirements.txt
27setenv = PYTHONPATH={toxinidir}/lib
2827
29[testenv:func]28[testenv:func]
30changedir = {toxinidir}/tests/functional29changedir = {toxinidir}/tests/functional
@@ -39,7 +38,7 @@ deps = -r{toxinidir}/tests/functional/requirements.txt
3938
40[testenv:lint]39[testenv:lint]
41commands =40commands =
42 black --check --line-length 79 reactive lib tests41 black --check --line-length 88 reactive lib tests
43 flake842 flake8
44deps =43deps =
45 black44 black
@@ -75,5 +74,5 @@ exclude =
75# I100: Import statements are in the wrong order74# I100: Import statements are in the wrong order
7675
77ignore = H405,D100,D101,D102,D103,D104,D105,D107,D200,D202,D203,D204,D205,D208,D400,D401,I100,I201,W503,W50476ignore = H405,D100,D101,D102,D103,D104,D105,D107,D200,D202,D203,D204,D205,D208,D400,D401,I100,I201,W503,W504
78max-line-length = 7977max-line-length = 88
79max-complexity = 1078max-complexity = 10

Subscribers

People subscribed via source and target branches

to all changes: