graphite: 0.9.15 -> 1.0.2

Fixes: #29961

Also added the option:

  services.graphite.web.extraConfig

for configuring graphite_web.
This commit is contained in:
Bas van Dijk 2017-09-30 21:12:24 +02:00
parent 3fe7cddc30
commit 5b8ff5ed49
8 changed files with 144 additions and 27 deletions

View File

@ -372,6 +372,17 @@ sub getUnitInfo {
return $info;
}
# Fail if the given systemd unit is not in the "active" state.
sub requireActiveUnit {
my ($self, $unit) = @_;
$self->nest("checking if unit $unit has reached state 'active'", sub {
my $info = $self->getUnitInfo($unit);
my $state = $info->{ActiveState};
if ($state ne "active") {
die "Expected unit $unit to to be in state 'active' but it is in state $state\n";
};
});
}
# Wait for a systemd unit to reach the "active" state.
sub waitForUnit {

View File

@ -7,6 +7,19 @@ let
writeTextOrNull = f: t: mapNullable (pkgs.writeTextDir f) t;
dataDir = cfg.dataDir;
staticDir = cfg.dataDir + "/static";
graphiteLocalSettingsDir = pkgs.runCommand "graphite_local_settings"
{inherit graphiteLocalSettings;} ''
mkdir -p $out
ln -s $graphiteLocalSettings $out/graphite_local_settings.py
'';
graphiteLocalSettings = pkgs.writeText "graphite_local_settings.py" (
"STATIC_ROOT = '${staticDir}'\n" +
optionalString (! isNull config.time.timeZone) "TIME_ZONE = '${config.time.timeZone}'\n"
+ cfg.web.extraConfig
);
graphiteApiConfig = pkgs.writeText "graphite-api.yaml" ''
time_zone: ${config.time.timeZone}
@ -94,6 +107,15 @@ in {
default = 8080;
type = types.int;
};
extraConfig = mkOption {
type = types.str;
default = "";
description = ''
Graphite webapp settings. See:
<link xlink:href="http://graphite.readthedocs.io/en/latest/config-local-settings.html"/>
'';
};
};
api = {
@ -460,9 +482,13 @@ in {
];
};
penvPack = "${penv}/${pkgs.python.sitePackages}";
# opt/graphite/webapp contains graphite/settings.py
# explicitly adding pycairo in path because it cannot be imported via buildEnv
in "${penvPack}/opt/graphite/webapp:${penvPack}:${pkgs.pythonPackages.pycairo}/${pkgs.python.sitePackages}";
in concatStringsSep ":" [
"${graphiteLocalSettingsDir}"
"${penvPack}/opt/graphite/webapp"
"${penvPack}"
# explicitly adding pycairo in path because it cannot be imported via buildEnv
"${pkgs.pythonPackages.pycairo}/${pkgs.python.sitePackages}"
];
DJANGO_SETTINGS_MODULE = "graphite.settings";
GRAPHITE_CONF_DIR = configDir;
GRAPHITE_STORAGE_DIR = dataDir;
@ -470,9 +496,9 @@ in {
};
serviceConfig = {
ExecStart = ''
${pkgs.python27Packages.waitress}/bin/waitress-serve \
--host=${cfg.web.listenAddress} --port=${toString cfg.web.port} \
--call django.core.handlers.wsgi:WSGIHandler'';
${pkgs.python27Packages.waitress-django}/bin/waitress-serve-django \
--host=${cfg.web.listenAddress} --port=${toString cfg.web.port}
'';
User = "graphite";
Group = "graphite";
PermissionsStartOnly = true;
@ -482,16 +508,20 @@ in {
mkdir -p ${dataDir}/{whisper/,log/webapp/}
chmod 0700 ${dataDir}/{whisper/,log/webapp/}
# populate database
${pkgs.python27Packages.graphite_web}/bin/manage-graphite.py syncdb --noinput
${pkgs.pythonPackages.django_1_8}/bin/django-admin.py migrate --noinput
# create index
${pkgs.python27Packages.graphite_web}/bin/build-index.sh
chown -R graphite:graphite ${cfg.dataDir}
chown -R graphite:graphite ${dataDir}
touch ${dataDir}/db-created
fi
# Only collect static files when graphite_web changes.
if ! [ "${dataDir}/current_graphite_web" -ef "${pkgs.python27Packages.graphite_web}" ]; then
mkdir -p ${staticDir}
${pkgs.pythonPackages.django_1_8}/bin/django-admin.py collectstatic --noinput --clear
chown -R graphite:graphite ${staticDir}
ln -sfT "${pkgs.python27Packages.graphite_web}" "${dataDir}/current_graphite_web"
fi
'';
};

View File

@ -255,6 +255,7 @@ in rec {
tests.gnome3 = callTest tests/gnome3.nix {};
tests.gnome3-gdm = callTest tests/gnome3-gdm.nix {};
tests.grafama = callTest tests/grafana.nix {};
tests.graphite = callTest tests/graphite.nix {};
tests.hardened = callTest tests/hardened.nix { };
tests.hibernate = callTest tests/hibernate.nix {};
tests.hound = callTest tests/hound.nix {};

26
nixos/tests/graphite.nix Normal file
View File

@ -0,0 +1,26 @@
import ./make-test.nix ({ pkgs, ...} :
{
name = "graphite";
nodes = {
one =
{ config, pkgs, ... }: {
services.graphite = {
web = {
enable = true;
};
carbon = {
enableCache = true;
};
};
};
};
testScript = ''
startAll;
$one->waitForUnit("default.target");
$one->requireActiveUnit("graphiteWeb.service");
$one->requireActiveUnit("carbonCache.service");
$one->succeed("echo \"foo 1 `date +%s`\" | nc -q0 localhost 2003");
$one->waitUntilSucceeds("curl 'http://localhost:8080/metrics/find/?query=foo&format=treejson' --silent | grep foo")
'';
})

View File

@ -0,0 +1,8 @@
{ buildPythonPackage, django_1_8, waitress }:
buildPythonPackage {
name = "waitress-django";
src = ./.;
pythonPath = [ django_1_8 waitress ];
doCheck = false;
meta.description = "A waitress WSGI server serving django";
}

View File

@ -0,0 +1,12 @@
#!/usr/bin/env python
from distutils.core import setup
setup( name = "waitress-django"
, version = "0.0.0"
, description = "A waitress WSGI server serving django"
, author = "Bas van Dijk"
, author_email = "v.dijk.bas@gmail.com"
, package_dir = {"" : "src"}
, scripts = ["src/waitress-serve-django"]
)

View File

@ -0,0 +1,14 @@
#!/usr/bin/env python
import sys
from waitress import serve
from waitress.adjustments import Adjustments
import django
from django.core.handlers.wsgi import WSGIHandler
from django.contrib.staticfiles.handlers import StaticFilesHandler
if __name__ == "__main__":
kw, args = Adjustments.parse_args(sys.argv[1:])
django.setup()
# These arguments are specific to the runner, not waitress itself.
del kw['call'], kw['help']
serve(StaticFilesHandler(WSGIHandler()), **kw)

View File

@ -60,7 +60,7 @@ let
buildPythonApplication = args: buildPythonPackage ({namePrefix="";} // args );
graphiteVersion = "0.9.15";
graphiteVersion = "1.0.2";
fetchPypi = makeOverridable( {format ? "setuptools", ... } @attrs:
let
@ -8299,14 +8299,14 @@ in {
django_tagging = callPackage ../development/python-modules/django_tagging { };
django_tagging_0_3 = self.django_tagging.overrideAttrs (attrs: rec {
name = "django-tagging-0.3.6";
django_tagging_0_4_3 = self.django_tagging.overrideAttrs (attrs: rec {
name = "django-tagging-0.4.3";
src = pkgs.fetchurl {
url = "mirror://pypi/d/django-tagging/${name}.tar.gz";
sha256 = "03zlbq13rydfh28wh0jk3x3cjk9x6jjmqnx1i3ngjmfwbxf8x6j1";
sha256 = "0617azpmp6jpg3d88v2ir97qrc9aqcs2s9gyvv9bgf2cp55khxhs";
};
propagatedBuildInputs = with self; [ django ];
propagatedBuildInputs = with self; [ django_1_8 ];
});
django_classytags = buildPythonPackage rec {
@ -22278,11 +22278,11 @@ EOF
};
waitress = buildPythonPackage rec {
name = "waitress-0.8.9";
name = "waitress-1.0.2";
src = pkgs.fetchurl {
url = "mirror://pypi/w/waitress/${name}.tar.gz";
sha256 = "826527dc9d334ed4ed76cdae672fdcbbccf614186657db71679ab58df869458a";
sha256 = "0pw6yyxi348r2xpq3ykqnf7gwi881azv2422d2ixb0xi5jws2ky7";
};
doCheck = false;
@ -22293,6 +22293,8 @@ EOF
};
};
waitress-django = callPackage ../development/python-modules/waitress-django { };
webassets = buildPythonPackage rec {
name = "webassets-${version}";
version = "0.12.1";
@ -23485,7 +23487,7 @@ EOF
src = pkgs.fetchurl {
url = "mirror://pypi/w/whisper/${name}.tar.gz";
sha256 = "1chkphxwnwvy2cs7jc2h2i0lqqvi9jx6vqj3ly88lwk7m35r4ss2";
sha256 = "1v1bi3fl1i6p4z4ki692bykrkw6907dn3mfq0151f70lvi3zpns3";
};
# error: invalid command 'test'
@ -23552,7 +23554,7 @@ EOF
src = pkgs.fetchurl {
url = "mirror://pypi/c/carbon/${name}.tar.gz";
sha256 = "f01db6d37726c6fc0a8aaa66a7bf14436b0dd0d62ef3c20ecb31605a4d365d2e";
sha256 = "142smpmgbnjinvfb6s4ijazish4vfgzyd8zcmdkh55y051fkixkn";
};
propagatedBuildInputs = with self; [ whisper txamqp zope_interface twisted ];
@ -23767,10 +23769,13 @@ EOF
src = pkgs.fetchurl rec {
url = "mirror://pypi/g/graphite-web/${name}.tar.gz";
sha256 = "1c0kclbv8shv9nvjx19wqm4asia58s3qmd9fapchc6y9fjpjax6q";
sha256 = "0q8bwlj75jqyzmazfsi5sa26xl58ssa8wdxm2l4j0jqyn8xpfnmc";
};
propagatedBuildInputs = with self; [ django django_tagging_0_3 whisper pycairo ldap memcached pytz ];
propagatedBuildInputs = with self; [
django_1_8 django_tagging_0_4_3 whisper pycairo cairocffi
ldap memcached pytz urllib3 scandir
];
postInstall = ''
wrapProgram $out/bin/run-graphite-devel-server.py \
@ -23778,10 +23783,20 @@ EOF
'';
preConfigure = ''
substituteInPlace webapp/graphite/thirdparty/pytz/__init__.py --replace '/usr/share/zoneinfo' '/etc/zoneinfo'
substituteInPlace webapp/graphite/settings.py --replace "join(WEBAPP_DIR, 'content')" "join('$out', 'webapp', 'content')"
cp webapp/graphite/manage.py bin/manage-graphite.py
substituteInPlace bin/manage-graphite.py --replace 'settings' 'graphite.settings'
# graphite is configured by storing a local_settings.py file inside the
# graphite python package. Since that package is stored in the immutable
# Nix store we can't modify it. So how do we configure graphite?
#
# First of all we rename "graphite.local_settings" to
# "graphite_local_settings" so that the settings are not looked up in the
# graphite package anymore. Secondly we place a directory containing a
# graphite_local_settings.py on the PYTHONPATH in the graphite module
# <nixpkgs/nixos/modules/services/monitoring/graphite.nix>.
substituteInPlace webapp/graphite/settings.py \
--replace "graphite.local_settings" " graphite_local_settings"
substituteInPlace webapp/graphite/settings.py \
--replace "join(WEBAPP_DIR, 'content')" "join('$out', 'webapp', 'content')"
'';
# error: invalid command 'test'