Skip to content

Commit ed10568

Browse files
committed
plugins {list,status}: Add --id option, to inquire individual plugins
Also, test status inquiry after plugin uninstall.
1 parent 4fcf1b5 commit ed10568

File tree

4 files changed

+90
-37
lines changed

4 files changed

+90
-37
lines changed

grafana_wtf/commands.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ def run():
3737
grafana-wtf [options] find [<search-expression>]
3838
grafana-wtf [options] replace <search-expression> <replacement> [--dry-run]
3939
grafana-wtf [options] log [<dashboard_uid>] [--number=<count>] [--head=<count>] [--tail=<count>] [--reverse] [--sql=<sql>]
40-
grafana-wtf [options] plugins list
41-
grafana-wtf [options] plugins status
40+
grafana-wtf [options] plugins list [--id=]
41+
grafana-wtf [options] plugins status [--id=]
4242
grafana-wtf --version
4343
grafana-wtf (-h | --help)
4444
@@ -324,9 +324,15 @@ def run():
324324

325325
if options.plugins:
326326
if options.list:
327-
response = engine.plugins_list()
327+
if options.id:
328+
response = engine.plugins_list_by_id(options.id)
329+
else:
330+
response = engine.plugins_list()
328331
elif options.status:
329-
response = engine.plugins_status()
332+
if options.id:
333+
response = engine.plugins_status_by_id(options.id)
334+
else:
335+
response = engine.plugins_status()
330336
else:
331337
raise DocoptExit('Subcommand "plugins" only provides "list" and "status"')
332338
output_results(output_format, response)

grafana_wtf/core.py

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -493,39 +493,50 @@ def explore_dashboards(self, with_data_details: bool = False):
493493
return results
494494

495495
def plugins_list(self):
496-
return self.grafana.plugin.get_installed_plugins()
496+
return self.grafana.plugin.list()
497497

498498
def plugins_status(self):
499499
status = []
500-
plugins = self.grafana.plugin.get_installed_plugins()
500+
plugins = self.grafana.plugin.list()
501501
for plugin in plugins:
502-
plugin = munchify(plugin)
503-
item = Munch(
504-
name=plugin.name,
505-
type=plugin.type,
506-
id=plugin.id,
507-
enabled=plugin.enabled,
508-
category=plugin.category,
509-
version=plugin.info.version,
510-
signature=plugin.get("signature"),
511-
)
512-
513-
# Status inquiry is not provided by all plugins. Let's filter them.
514-
# Effectively, run it only on non-internal "app" and "datasource" items.
515-
if item.type != "panel" and item.signature != "internal":
516-
try:
517-
item.health = self.grafana.plugin.health_check_plugin(plugin.id)
518-
except Exception as ex:
519-
log.warning(f"Health check failed for plugin {item.id}, type={item.type}: {ex}")
520-
try:
521-
item.metrics = self.grafana.plugin.get_plugin_metrics(plugin.id)
522-
except Exception as ex:
523-
log.warning(f"Metrics inquiry failed for plugin {item.id}, type={item.type}: {ex}")
524-
else:
525-
log.info(f"Skipping status inquiry for plugin {item.id}, type={item.type}")
502+
item = self.get_plugin_status(plugin)
526503
status.append(item)
527504
return status
528505

506+
def get_plugin_status(self, plugin):
507+
plugin = munchify(plugin)
508+
item = Munch(
509+
name=plugin.name,
510+
type=plugin.type,
511+
id=plugin.id,
512+
enabled=plugin.enabled,
513+
category=plugin.category,
514+
version=plugin.info.version,
515+
signature=plugin.get("signature"),
516+
)
517+
518+
# Status inquiry is not provided by all plugins. Let's filter them.
519+
# Effectively, run it only on non-internal "app" and "datasource" items.
520+
if item.type != "panel" and item.signature != "internal":
521+
try:
522+
item.health = self.grafana.plugin.health(plugin.id)
523+
except Exception as ex:
524+
log.warning(f"Health check failed for plugin {item.id}, type={item.type}: {ex}")
525+
try:
526+
item.metrics = self.grafana.plugin.metrics(plugin.id)
527+
except Exception as ex:
528+
log.warning(f"Metrics inquiry failed for plugin {item.id}, type={item.type}: {ex}")
529+
else:
530+
log.info(f"Skipping status inquiry for plugin {item.id}, type={item.type}")
531+
return item
532+
533+
def plugins_list_by_id(self, plugin_id):
534+
return self.grafana.plugin.by_id(plugin_id=plugin_id)
535+
536+
def plugins_status_by_id(self, plugin_id):
537+
plugin = self.plugins_list_by_id(plugin_id)
538+
return self.get_plugin_status(plugin)
539+
529540

530541
class Indexer:
531542
def __init__(self, engine: GrafanaWtf):

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
f"duckdb<0.9; {no_linux_on_arm}",
2121
# Grafana
2222
"requests>=2.26,<3",
23-
"grafana-client>=3.8.2,<4",
23+
"grafana-client>=3.9.1,<4",
2424
"jsonpath-rw>=1.4.0,<2",
2525
# Caching
2626
"requests-cache>=0.8.0,<2",

tests/test_commands.py

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import warnings
22

33
import grafana_client
4-
from grafana_client.elements.plugin import filter_plugin_by_id
4+
from grafana_client.elements.plugin import get_plugin_by_id
55
from munch import munchify
66
from packaging import version
77

@@ -576,7 +576,7 @@ def test_plugins_list(docker_grafana, capsys, caplog):
576576
assert len(data) >= 28
577577

578578
# Proof the output is correct.
579-
plugin = munchify(filter_plugin_by_id(plugin_list=data, plugin_id="alertlist"))
579+
plugin = munchify(get_plugin_by_id(plugin_list=data, plugin_id="alertlist"))
580580
assert plugin.name.title() == "Alert List"
581581
assert plugin.type == "panel"
582582
assert plugin.id == "alertlist"
@@ -598,7 +598,7 @@ def test_plugins_status_datasource(grafana_version, docker_grafana, capsys, capl
598598

599599
# Before conducting a plugin status test, install a non-internal one.
600600
grafana = grafana_client.GrafanaApi.from_url(url=docker_grafana, timeout=15)
601-
grafana.plugin.install_plugin("yesoreyeram-infinity-datasource")
601+
grafana.plugin.install("yesoreyeram-infinity-datasource")
602602

603603
# Which subcommand to test?
604604
set_command("plugins status", "--format=yaml")
@@ -613,7 +613,7 @@ def test_plugins_status_datasource(grafana_version, docker_grafana, capsys, capl
613613
assert len(data) >= 28
614614

615615
# Proof the output is correct.
616-
plugin = munchify(filter_plugin_by_id(plugin_list=data, plugin_id="yesoreyeram-infinity-datasource"))
616+
plugin = munchify(get_plugin_by_id(plugin_list=data, plugin_id="yesoreyeram-infinity-datasource"))
617617
assert "go_gc_duration_seconds" in plugin.metrics
618618

619619

@@ -626,7 +626,7 @@ def test_plugins_status_app(grafana_version, docker_grafana, capsys, caplog):
626626

627627
# Before conducting a plugin status test, install a non-internal one.
628628
grafana = grafana_client.GrafanaApi.from_url(url=docker_grafana, timeout=15)
629-
grafana.plugin.install_plugin("aws-datasource-provisioner-app")
629+
grafana.plugin.install("aws-datasource-provisioner-app")
630630

631631
# Which subcommand to test?
632632
set_command("plugins status", "--format=yaml")
@@ -641,6 +641,42 @@ def test_plugins_status_app(grafana_version, docker_grafana, capsys, caplog):
641641
assert len(data) >= 28
642642

643643
# Proof the output is correct.
644-
plugin = munchify(filter_plugin_by_id(plugin_list=data, plugin_id="aws-datasource-provisioner-app"))
644+
plugin = munchify(get_plugin_by_id(plugin_list=data, plugin_id="aws-datasource-provisioner-app"))
645645
assert "process_virtual_memory_max_bytes" in plugin.metrics
646646
assert plugin.health == {"message": "", "status": "OK"}
647+
648+
649+
def test_plugins_install_uninstall(grafana_version, docker_grafana, capsys, caplog):
650+
"""
651+
Verify the plugin status when installing/uninstalling a plugin.
652+
"""
653+
if version.parse(grafana_version) < version.parse("8"):
654+
raise pytest.skip(f"Plugin status inquiry only works on Grafana 8 and newer")
655+
656+
plugin_name = "yesoreyeram-infinity-datasource"
657+
658+
# Before conducting a plugin status test, install a non-internal one.
659+
grafana = grafana_client.GrafanaApi.from_url(url=docker_grafana, timeout=15)
660+
grafana.plugin.install(plugin_name)
661+
662+
# Which subcommand to test?
663+
set_command(f"plugins status --id={plugin_name}", "--format=yaml")
664+
665+
# Run command and capture YAML output.
666+
with caplog.at_level(logging.DEBUG):
667+
grafana_wtf.commands.run()
668+
captured = capsys.readouterr()
669+
plugin_status = munchify(yaml.safe_load(captured.out))
670+
671+
# Proof the output is correct.
672+
assert plugin_status.id == plugin_name
673+
assert version.parse(plugin_status.version) >= version.parse("2.0.0")
674+
assert "go_gc_duration_seconds" in plugin_status.metrics
675+
676+
# Uninstall the plugin again.
677+
grafana.plugin.uninstall(plugin_name)
678+
679+
# Verify uninstalling worked.
680+
with pytest.raises(KeyError) as ex:
681+
grafana_wtf.commands.run()
682+
assert ex.match("Plugin not found: yesoreyeram-infinity-datasource")

0 commit comments

Comments
 (0)