at master 6.2 kB view raw
1{ 2 config, 3 pkgs, 4 lib, 5 ... 6}: 7with lib; 8let 9 cfg = config.services.vmalert; 10 11 format = pkgs.formats.yaml { }; 12 13 mkConfOpts = 14 settings: 15 concatStringsSep " \\\n" (mapAttrsToList mkLine (filterAttrs (_: v: v != false) settings)); 16 confType = 17 with types; 18 let 19 valueType = oneOf [ 20 bool 21 int 22 path 23 str 24 ]; 25 in 26 attrsOf (either valueType (listOf valueType)); 27 28 mkLine = 29 key: value: 30 if value == true then 31 "-${key}" 32 else if isList value then 33 concatMapStringsSep " " (v: "-${key}=${escapeShellArg (toString v)}") value 34 else 35 "-${key}=${escapeShellArg (toString value)}"; 36 37 vmalertName = name: "vmalert" + lib.optionalString (name != "") ("-" + name); 38 enabledInstances = lib.filterAttrs (name: conf: conf.enable) config.services.vmalert.instances; 39in 40{ 41 imports = [ 42 (lib.mkRenamedOptionModule 43 [ "services" "vmalert" "enable" ] 44 [ "services" "vmalert" "instances" "" "enable" ] 45 ) 46 (lib.mkRenamedOptionModule 47 [ "services" "vmalert" "rules" ] 48 [ "services" "vmalert" "instances" "" "rules" ] 49 ) 50 (lib.mkRenamedOptionModule 51 [ "services" "vmalert" "settings" ] 52 [ "services" "vmalert" "instances" "" "settings" ] 53 ) 54 ]; 55 56 # interface 57 options.services.vmalert.package = mkPackageOption pkgs "victoriametrics" { }; 58 59 options.services.vmalert.instances = mkOption { 60 default = { }; 61 62 description = '' 63 Define multiple instances of vmalert. 64 ''; 65 66 type = types.attrsOf ( 67 types.submodule ( 68 { name, config, ... }: 69 { 70 options = { 71 enable = lib.mkOption { 72 type = lib.types.bool; 73 default = false; 74 description = '' 75 Wether to enable VictoriaMetrics's `vmalert`. 76 77 `vmalert` evaluates alerting and recording rules against a data source, sends notifications via Alertmanager. 78 ''; 79 }; 80 81 settings = mkOption { 82 type = types.submodule { 83 freeformType = confType; 84 options = { 85 86 "datasource.url" = mkOption { 87 type = types.nonEmptyStr; 88 example = "http://localhost:8428"; 89 description = '' 90 Datasource compatible with Prometheus HTTP API. 91 ''; 92 }; 93 94 "notifier.url" = mkOption { 95 type = with types; listOf nonEmptyStr; 96 default = [ ]; 97 example = [ "http://127.0.0.1:9093" ]; 98 description = '' 99 Prometheus Alertmanager URL. List all Alertmanager URLs if it runs in the cluster mode to ensure high availability. 100 ''; 101 }; 102 103 "rule" = mkOption { 104 type = with types; listOf path; 105 description = '' 106 Path to the files with alerting and/or recording rules. 107 108 ::: {.note} 109 Consider using the {option}`services.vmalert.instances.<name>.rules` option as a convenient alternative for declaring rules 110 directly in the `nix` language. 111 ::: 112 ''; 113 }; 114 115 }; 116 }; 117 default = { }; 118 example = { 119 "datasource.url" = "http://localhost:8428"; 120 "datasource.disableKeepAlive" = true; 121 "datasource.showURL" = false; 122 "rule" = [ 123 "http://<some-server-addr>/path/to/rules" 124 "dir/*.yaml" 125 ]; 126 }; 127 description = '' 128 `vmalert` configuration, passed via command line flags. Refer to 129 <https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/app/vmalert/README.md#configuration> 130 for details on supported values. 131 ''; 132 }; 133 134 rules = mkOption { 135 type = format.type; 136 default = { }; 137 example = { 138 group = [ 139 { 140 name = "TestGroup"; 141 rules = [ 142 { 143 alert = "ExampleAlertAlwaysFiring"; 144 expr = '' 145 sum by(job) 146 (up == 1) 147 ''; 148 } 149 ]; 150 } 151 ]; 152 }; 153 description = '' 154 A list of the given alerting or recording rules against configured `"datasource.url"` compatible with 155 Prometheus HTTP API for `vmalert` to execute. Refer to 156 <https://github.com/VictoriaMetrics/VictoriaMetrics/blob/master/app/vmalert/README.md#rules> 157 for details on supported values. 158 ''; 159 }; 160 }; 161 162 config = { 163 settings.rule = [ 164 "/etc/${vmalertName name}/rules.yml" 165 ]; 166 }; 167 } 168 ) 169 ); 170 }; 171 172 # implementation 173 config = mkIf (enabledInstances != { }) { 174 environment.etc = lib.mapAttrs' ( 175 name: 176 { rules, ... }: 177 lib.nameValuePair "${vmalertName name}/rules.yml" { 178 source = format.generate "rules.yml" rules; 179 } 180 ) enabledInstances; 181 182 systemd.services = lib.mapAttrs' ( 183 name: 184 { settings, ... }: 185 let 186 name' = vmalertName name; 187 in 188 lib.nameValuePair name' { 189 description = "vmalert service"; 190 wantedBy = [ "multi-user.target" ]; 191 after = [ "network.target" ]; 192 reloadTriggers = [ config.environment.etc."${name'}/rules.yml".source ]; 193 194 serviceConfig = { 195 DynamicUser = true; 196 Restart = "on-failure"; 197 ExecStart = "${cfg.package}/bin/vmalert ${mkConfOpts settings}"; 198 ExecReload = ''${pkgs.coreutils}/bin/kill -SIGHUP "$MAINPID"''; 199 }; 200 } 201 ) enabledInstances; 202 }; 203}