diff --git a/nixos/modules/services/monitoring/grafana.nix b/nixos/modules/services/monitoring/grafana.nix index b0c81a46d4d817..c8515c4b8988c9 100644 --- a/nixos/modules/services/monitoring/grafana.nix +++ b/nixos/modules/services/monitoring/grafana.nix @@ -5,10 +5,11 @@ with lib; let cfg = config.services.grafana; opt = options.services.grafana; + declarativePlugins = pkgs.linkFarm "grafana-plugins" (builtins.map (pkg: { name = pkg.pname; path = pkg; }) cfg.declarativePlugins); envOptions = { PATHS_DATA = cfg.dataDir; - PATHS_PLUGINS = "${cfg.dataDir}/plugins"; + PATHS_PLUGINS = if builtins.isNull cfg.declarativePlugins then "${cfg.dataDir}/plugins" else declarativePlugins; PATHS_LOGS = "${cfg.dataDir}/log"; SERVER_PROTOCOL = cfg.protocol; @@ -260,6 +261,12 @@ in { defaultText = "pkgs.grafana"; type = types.package; }; + declarativePlugins = mkOption { + type = with types; nullOr (listOf path); + default = null; + description = "If non-null, then a list of packages containing Grafana plugins to install. If set, plugins cannot be manually installed."; + example = literalExample "with pkgs.grafanaPlugins; [ grafana-piechart-panel ]"; + }; dataDir = mkOption { description = "Data directory."; diff --git a/nixos/tests/grafana.nix b/nixos/tests/grafana.nix index 4b453ece7f1ef6..4ba091b893f42b 100644 --- a/nixos/tests/grafana.nix +++ b/nixos/tests/grafana.nix @@ -17,6 +17,10 @@ let }; extraNodeConfs = { + declarativePlugins = { + services.grafana.declarativePlugins = [ pkgs.grafanaPlugins.grafana-clock-panel ]; + }; + postgresql = { services.grafana.database = { host = "127.0.0.1:5432"; @@ -52,7 +56,7 @@ let nameValuePair dbName (mkMerge [ baseGrafanaConf (extraNodeConfs.${dbName} or {}) - ])) [ "sqlite" "postgresql" "mysql" ]); + ])) [ "sqlite" "declarativePlugins" "postgresql" "mysql" ]); in { name = "grafana"; @@ -66,6 +70,14 @@ in { testScript = '' start_all() + with subtest("Declarative plugins installed"): + declarativePlugins.wait_for_unit("grafana.service") + declarativePlugins.wait_for_open_port(3000) + declarativePlugins.succeed( + "curl -sSfN -u testadmin:snakeoilpwd http://127.0.0.1:3000/api/plugins | grep -q grafana-clock-panel" + ) + declarativePlugins.shutdown() + with subtest("Successful API query as admin user with sqlite db"): sqlite.wait_for_unit("grafana.service") sqlite.wait_for_open_port(3000) diff --git a/pkgs/servers/monitoring/grafana/plugins/default.nix b/pkgs/servers/monitoring/grafana/plugins/default.nix new file mode 100644 index 00000000000000..95be470831c1d3 --- /dev/null +++ b/pkgs/servers/monitoring/grafana/plugins/default.nix @@ -0,0 +1,7 @@ +{ newScope, pkgs }: + +let + callPackage = newScope (pkgs // plugins); + plugins = import ./plugins.nix { inherit callPackage; }; +in + plugins diff --git a/pkgs/servers/monitoring/grafana/plugins/grafana-clock-panel/default.nix b/pkgs/servers/monitoring/grafana/plugins/grafana-clock-panel/default.nix new file mode 100644 index 00000000000000..c0648c97e68bcf --- /dev/null +++ b/pkgs/servers/monitoring/grafana/plugins/grafana-clock-panel/default.nix @@ -0,0 +1,13 @@ +{ grafanaPlugin, lib }: + +grafanaPlugin rec { + pname = "grafana-clock-panel"; + version = "1.1.1"; + zipHash = "sha256-SvZyg7r+XG6i7jqYwxpPn6ZzJc7qmtfPtyphYppURDk="; + meta = with lib; { + description = "Clock panel for Grafana"; + license = licenses.asl20; + maintainers = with maintainers; [ lukegb ]; + platforms = platforms.unix; + }; +} diff --git a/pkgs/servers/monitoring/grafana/plugins/grafana-piechart-panel/default.nix b/pkgs/servers/monitoring/grafana/plugins/grafana-piechart-panel/default.nix new file mode 100644 index 00000000000000..2c44d3a4a062f5 --- /dev/null +++ b/pkgs/servers/monitoring/grafana/plugins/grafana-piechart-panel/default.nix @@ -0,0 +1,13 @@ +{ grafanaPlugin, lib }: + +grafanaPlugin rec { + pname = "grafana-piechart-panel"; + version = "1.6.1"; + zipHash = "sha256-64K/efoBKuBFp8Jw79hTdMyTurTZsL0qfgPDcUWz2jg="; + meta = with lib; { + description = "Pie chart panel for Grafana"; + license = licenses.asl20; + maintainers = with maintainers; [ lukegb ]; + platforms = platforms.unix; + }; +} diff --git a/pkgs/servers/monitoring/grafana/plugins/grafana-plugin.nix b/pkgs/servers/monitoring/grafana/plugins/grafana-plugin.nix new file mode 100644 index 00000000000000..3b3cee88fd7a1f --- /dev/null +++ b/pkgs/servers/monitoring/grafana/plugins/grafana-plugin.nix @@ -0,0 +1,28 @@ +{ stdenvNoCC, fetchurl, unzip }: + +{ pname, version, zipHash, meta ? {}, passthru ? {}, ... }@args: +stdenvNoCC.mkDerivation ({ + inherit pname version; + + src = fetchurl { + name = "${pname}-${version}.zip"; + url = "https://grafana.com/api/plugins/${pname}/versions/${version}/download"; + hash = zipHash; + }; + + nativeBuildInputs = [ unzip ]; + + installPhase = '' + cp -R "." "$out" + chmod -R a-w "$out" + chmod u+w "$out" + ''; + + passthru = { + updateScript = [ ./update-grafana-plugin.sh pname ]; + } // passthru; + + meta = { + homepage = "https://grafana.com/grafana/plugins/${pname}"; + } // meta; +} // (builtins.removeAttrs args [ "pname" "version" "sha256" "meta" ])) diff --git a/pkgs/servers/monitoring/grafana/plugins/grafana-polystat-panel/default.nix b/pkgs/servers/monitoring/grafana/plugins/grafana-polystat-panel/default.nix new file mode 100644 index 00000000000000..efbaeda9376263 --- /dev/null +++ b/pkgs/servers/monitoring/grafana/plugins/grafana-polystat-panel/default.nix @@ -0,0 +1,13 @@ +{ grafanaPlugin, lib }: + +grafanaPlugin rec { + pname = "grafana-polystat-panel"; + version = "1.2.2"; + zipHash = "sha256-HWQdhstnrDuXPithZ8kOG2ZtSeAT215MJ1ftMCt6/tc="; + meta = with lib; { + description = "Hexagonal multi-stat panel for Grafana"; + license = licenses.asl20; + maintainers = with maintainers; [ lukegb ]; + platforms = platforms.unix; + }; +} diff --git a/pkgs/servers/monitoring/grafana/plugins/grafana-worldmap-panel/default.nix b/pkgs/servers/monitoring/grafana/plugins/grafana-worldmap-panel/default.nix new file mode 100644 index 00000000000000..2f1671750fa574 --- /dev/null +++ b/pkgs/servers/monitoring/grafana/plugins/grafana-worldmap-panel/default.nix @@ -0,0 +1,13 @@ +{ grafanaPlugin, lib }: + +grafanaPlugin rec { + pname = "grafana-worldmap-panel"; + version = "0.3.2"; + zipHash = "sha256-MGAJzS9X91x6wt305jH1chLoW3zd7pIYDwRnPg9qrgE="; + meta = with lib; { + description = "World Map panel for Grafana"; + license = licenses.asl20; + maintainers = with maintainers; [ lukegb ]; + platforms = platforms.unix; + }; +} diff --git a/pkgs/servers/monitoring/grafana/plugins/plugins.nix b/pkgs/servers/monitoring/grafana/plugins/plugins.nix new file mode 100644 index 00000000000000..b2991ba4e74e77 --- /dev/null +++ b/pkgs/servers/monitoring/grafana/plugins/plugins.nix @@ -0,0 +1,11 @@ +{ callPackage }: +{ + inherit callPackage; + + grafanaPlugin = callPackage ./grafana-plugin.nix { }; + + grafana-clock-panel = callPackage ./grafana-clock-panel { }; + grafana-piechart-panel = callPackage ./grafana-piechart-panel { }; + grafana-polystat-panel = callPackage ./grafana-polystat-panel { }; + grafana-worldmap-panel = callPackage ./grafana-worldmap-panel { }; +} diff --git a/pkgs/servers/monitoring/grafana/plugins/update-grafana-plugin.sh b/pkgs/servers/monitoring/grafana/plugins/update-grafana-plugin.sh new file mode 100755 index 00000000000000..dd8f050c633c48 --- /dev/null +++ b/pkgs/servers/monitoring/grafana/plugins/update-grafana-plugin.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash -p curl jq common-updater-scripts + +set -eu -o pipefail + +readonly plugin_name="$1" +readonly latest_version="$(curl "https://grafana.com/api/plugins/${plugin_name}" | jq -r .version)" +update-source-version "grafanaPlugins.${plugin_name}" "$latest_version" diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 27c565bce0c71d..a0aa129526a8cd 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -17164,6 +17164,7 @@ in gofish = callPackage ../servers/gopher/gofish { }; grafana = callPackage ../servers/monitoring/grafana { }; + grafanaPlugins = dontRecurseIntoAttrs (callPackage ../servers/monitoring/grafana/plugins { }); grafana-loki = callPackage ../servers/monitoring/loki { };