at 22.05-pre 9.3 kB view raw
1# To run the test on the unfree ELK use the folllowing command: 2# cd path/to/nixpkgs 3# NIXPKGS_ALLOW_UNFREE=1 nix-build -A nixosTests.elk.unfree.ELK-6 4 5{ system ? builtins.currentSystem, 6 config ? {}, 7 pkgs ? import ../.. { inherit system config; }, 8}: 9 10let 11 inherit (pkgs) lib; 12 13 esUrl = "http://localhost:9200"; 14 15 mkElkTest = name : elk : 16 import ./make-test-python.nix ({ 17 inherit name; 18 meta = with pkgs.lib.maintainers; { 19 maintainers = [ eelco offline basvandijk ]; 20 }; 21 nodes = { 22 one = 23 { pkgs, lib, ... }: { 24 # Not giving the machine at least 2060MB results in elasticsearch failing with the following error: 25 # 26 # OpenJDK 64-Bit Server VM warning: 27 # INFO: os::commit_memory(0x0000000085330000, 2060255232, 0) 28 # failed; error='Cannot allocate memory' (errno=12) 29 # 30 # There is insufficient memory for the Java Runtime Environment to continue. 31 # Native memory allocation (mmap) failed to map 2060255232 bytes for committing reserved memory. 32 # 33 # When setting this to 2500 I got "Kernel panic - not syncing: Out of 34 # memory: compulsory panic_on_oom is enabled" so lets give it even a 35 # bit more room: 36 virtualisation.memorySize = 3000; 37 38 # For querying JSON objects returned from elasticsearch and kibana. 39 environment.systemPackages = [ pkgs.jq ]; 40 41 services = { 42 43 journalbeat = let lt6 = builtins.compareVersions 44 elk.journalbeat.version "6" < 0; in { 45 enable = true; 46 package = elk.journalbeat; 47 extraConfig = pkgs.lib.mkOptionDefault ('' 48 logging: 49 to_syslog: true 50 level: warning 51 metrics.enabled: false 52 output.elasticsearch: 53 hosts: [ "127.0.0.1:9200" ] 54 ${pkgs.lib.optionalString lt6 "template.enabled: false"} 55 '' + pkgs.lib.optionalString (!lt6) '' 56 journalbeat.inputs: 57 - paths: [] 58 seek: cursor 59 ''); 60 }; 61 62 metricbeat = { 63 enable = true; 64 package = elk.metricbeat; 65 modules.system = { 66 metricsets = ["cpu" "load" "memory" "network" "process" "process_summary" "uptime" "socket_summary"]; 67 enabled = true; 68 period = "5s"; 69 processes = [".*"]; 70 cpu.metrics = ["percentages" "normalized_percentages"]; 71 core.metrics = ["percentages"]; 72 }; 73 settings = { 74 output.elasticsearch = { 75 hosts = ["127.0.0.1:9200"]; 76 }; 77 }; 78 }; 79 80 logstash = { 81 enable = true; 82 package = elk.logstash; 83 inputConfig = '' 84 exec { command => "echo -n flowers" interval => 1 type => "test" } 85 exec { command => "echo -n dragons" interval => 1 type => "test" } 86 ''; 87 filterConfig = '' 88 if [message] =~ /dragons/ { 89 drop {} 90 } 91 ''; 92 outputConfig = '' 93 file { 94 path => "/tmp/logstash.out" 95 codec => line { format => "%{message}" } 96 } 97 elasticsearch { 98 hosts => [ "${esUrl}" ] 99 } 100 ''; 101 }; 102 103 elasticsearch = { 104 enable = true; 105 package = elk.elasticsearch; 106 }; 107 108 kibana = { 109 enable = true; 110 package = elk.kibana; 111 }; 112 113 elasticsearch-curator = { 114 enable = true; 115 actionYAML = '' 116 --- 117 actions: 118 1: 119 action: delete_indices 120 description: >- 121 Delete indices older than 1 second (based on index name), for logstash- 122 prefixed indices. Ignore the error if the filter does not result in an 123 actionable list of indices (ignore_empty_list) and exit cleanly. 124 options: 125 allow_ilm_indices: true 126 ignore_empty_list: True 127 disable_action: False 128 filters: 129 - filtertype: pattern 130 kind: prefix 131 value: logstash- 132 - filtertype: age 133 source: name 134 direction: older 135 timestring: '%Y.%m.%d' 136 unit: seconds 137 unit_count: 1 138 ''; 139 }; 140 }; 141 }; 142 }; 143 144 passthru.elkPackages = elk; 145 testScript = '' 146 import json 147 148 149 def total_hits(message): 150 dictionary = {"query": {"match": {"message": message}}} 151 return ( 152 "curl --silent --show-error '${esUrl}/_search' " 153 + "-H 'Content-Type: application/json' " 154 + "-d '{}' ".format(json.dumps(dictionary)) 155 + "| jq .hits.total" 156 ) 157 158 159 def has_metricbeat(): 160 dictionary = {"query": {"match": {"event.dataset": {"query": "system.cpu"}}}} 161 return ( 162 "curl --silent --show-error '${esUrl}/_search' " 163 + "-H 'Content-Type: application/json' " 164 + "-d '{}' ".format(json.dumps(dictionary)) 165 + "| jq '.hits.total > 0'" 166 ) 167 168 169 start_all() 170 171 one.wait_for_unit("elasticsearch.service") 172 one.wait_for_open_port(9200) 173 174 # Continue as long as the status is not "red". The status is probably 175 # "yellow" instead of "green" because we are using a single elasticsearch 176 # node which elasticsearch considers risky. 177 # 178 # TODO: extend this test with multiple elasticsearch nodes 179 # and see if the status turns "green". 180 one.wait_until_succeeds( 181 "curl --silent --show-error '${esUrl}/_cluster/health' | jq .status | grep -v red" 182 ) 183 184 with subtest("Perform some simple logstash tests"): 185 one.wait_for_unit("logstash.service") 186 one.wait_until_succeeds("cat /tmp/logstash.out | grep flowers") 187 one.wait_until_succeeds("cat /tmp/logstash.out | grep -v dragons") 188 189 with subtest("Kibana is healthy"): 190 one.wait_for_unit("kibana.service") 191 one.wait_until_succeeds( 192 "curl --silent --show-error 'http://localhost:5601/api/status' | jq .status.overall.state | grep green" 193 ) 194 195 with subtest("Metricbeat is running"): 196 one.wait_for_unit("metricbeat.service") 197 198 with subtest("Metricbeat metrics arrive in elasticsearch"): 199 one.wait_until_succeeds(has_metricbeat() + " | tee /dev/console | grep 'true'") 200 201 with subtest("Logstash messages arive in elasticsearch"): 202 one.wait_until_succeeds(total_hits("flowers") + " | grep -v 0") 203 one.wait_until_succeeds(total_hits("dragons") + " | grep 0") 204 205 with subtest( 206 "A message logged to the journal is ingested by elasticsearch via journalbeat" 207 ): 208 one.wait_for_unit("journalbeat.service") 209 one.execute("echo 'Supercalifragilisticexpialidocious' | systemd-cat") 210 one.wait_until_succeeds( 211 total_hits("Supercalifragilisticexpialidocious") + " | grep -v 0" 212 ) 213 214 with subtest("Elasticsearch-curator works"): 215 one.systemctl("stop logstash") 216 one.systemctl("start elasticsearch-curator") 217 one.wait_until_succeeds( 218 '! curl --silent --show-error "${esUrl}/_cat/indices" | grep logstash | grep ^' 219 ) 220 ''; 221 }) { inherit pkgs system; }; 222in { 223 ELK-6 = mkElkTest "elk-6-oss" { 224 name = "elk-6-oss"; 225 elasticsearch = pkgs.elasticsearch6-oss; 226 logstash = pkgs.logstash6-oss; 227 kibana = pkgs.kibana6-oss; 228 journalbeat = pkgs.journalbeat6; 229 metricbeat = pkgs.metricbeat6; 230 }; 231 # We currently only package upstream binaries. 232 # Feel free to package an SSPL licensed source-based package! 233 # ELK-7 = mkElkTest "elk-7-oss" { 234 # name = "elk-7"; 235 # elasticsearch = pkgs.elasticsearch7-oss; 236 # logstash = pkgs.logstash7-oss; 237 # kibana = pkgs.kibana7-oss; 238 # journalbeat = pkgs.journalbeat7; 239 # metricbeat = pkgs.metricbeat7; 240 # }; 241 unfree = lib.dontRecurseIntoAttrs { 242 ELK-6 = mkElkTest "elk-6" { 243 elasticsearch = pkgs.elasticsearch6; 244 logstash = pkgs.logstash6; 245 kibana = pkgs.kibana6; 246 journalbeat = pkgs.journalbeat6; 247 metricbeat = pkgs.metricbeat6; 248 }; 249 ELK-7 = mkElkTest "elk-7" { 250 elasticsearch = pkgs.elasticsearch7; 251 logstash = pkgs.logstash7; 252 kibana = pkgs.kibana7; 253 journalbeat = pkgs.journalbeat7; 254 metricbeat = pkgs.metricbeat7; 255 }; 256 }; 257}