Merge pull request #107980 from lukegb/grafana-plugins

Add Nix packages for Grafana plugins and allow declarative installation

Changed files
+128 -2
nixos
modules
services
monitoring
tests
pkgs
servers
monitoring
grafana
plugins
grafana-clock-panel
grafana-piechart-panel
grafana-polystat-panel
grafana-worldmap-panel
top-level
+8 -1
nixos/modules/services/monitoring/grafana.nix
···
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;
···
default = pkgs.grafana;
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 {
+13 -1
nixos/tests/grafana.nix
···
};
extraNodeConfs = {
+
declarativePlugins = {
+
services.grafana.declarativePlugins = [ pkgs.grafanaPlugins.grafana-clock-panel ];
+
};
+
postgresql = {
services.grafana.database = {
host = "127.0.0.1:5432";
···
nameValuePair dbName (mkMerge [
baseGrafanaConf
(extraNodeConfs.${dbName} or {})
-
])) [ "sqlite" "postgresql" "mysql" ]);
+
])) [ "sqlite" "declarativePlugins" "postgresql" "mysql" ]);
in {
name = "grafana";
···
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")
+7
pkgs/servers/monitoring/grafana/plugins/default.nix
···
+
{ newScope, pkgs }:
+
+
let
+
callPackage = newScope (pkgs // plugins);
+
plugins = import ./plugins.nix { inherit callPackage; };
+
in
+
plugins
+13
pkgs/servers/monitoring/grafana/plugins/grafana-clock-panel/default.nix
···
+
{ 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;
+
};
+
}
+13
pkgs/servers/monitoring/grafana/plugins/grafana-piechart-panel/default.nix
···
+
{ 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;
+
};
+
}
+28
pkgs/servers/monitoring/grafana/plugins/grafana-plugin.nix
···
+
{ 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" ]))
+13
pkgs/servers/monitoring/grafana/plugins/grafana-polystat-panel/default.nix
···
+
{ 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;
+
};
+
}
+13
pkgs/servers/monitoring/grafana/plugins/grafana-worldmap-panel/default.nix
···
+
{ 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;
+
};
+
}
+11
pkgs/servers/monitoring/grafana/plugins/plugins.nix
···
+
{ 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 { };
+
}
+8
pkgs/servers/monitoring/grafana/plugins/update-grafana-plugin.sh
···
+
#!/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"
+1
pkgs/top-level/all-packages.nix
···
gofish = callPackage ../servers/gopher/gofish { };
grafana = callPackage ../servers/monitoring/grafana { };
+
grafanaPlugins = dontRecurseIntoAttrs (callPackage ../servers/monitoring/grafana/plugins { });
grafana-loki = callPackage ../servers/monitoring/loki { };