Merge ~hloeung/charm-graylog:master into ~graylog-charmers/charm-graylog:master

Proposed by Haw Loeung
Status: Merged
Approved by: Haw Loeung
Approved revision: 62a0100004fdda1a217eab595a727142e4159697
Merged at revision: efc18399977fbf5e6bd8a6fd2b8d745293b24382
Proposed branch: ~hloeung/charm-graylog:master
Merge into: ~graylog-charmers/charm-graylog:master
Diff against target: 532 lines (+236/-45)
11 files modified
.gitignore (+7/-3)
Makefile (+5/-10)
config.yaml (+5/-0)
files/check_graylog_health.py (+1/-1)
lib/logextract.py (+7/-7)
reactive/graylog.py (+69/-4)
requirements.txt (+1/-0)
tox.ini (+27/-0)
unit_tests/requirements.txt (+6/-0)
unit_tests/test_graylog.py (+94/-3)
unit_tests/test_logextract.py (+14/-17)
Reviewer Review Type Date Requested Status
Haw Loeung Needs Resubmitting
Joel Sing (community) +1 Approve
Review via email: mp+361477@code.launchpad.net

Commit message

Add option to tune JVM heap size - LP: #1807565

To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Unable to determine commit message from repository - please click "Set commit message" and enter the commit message manually.

Revision history for this message
Joel Sing (jsing) :
review: Needs Fixing
Revision history for this message
Joel Sing (jsing) :
Revision history for this message
Joel Sing (jsing) wrote :

LGTM, couple of minor comments inline.

review: Approve (+1)
Revision history for this message
Haw Loeung (hloeung) wrote :

Minor fixes without having to change existing code.

review: Needs Resubmitting
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Merge proposal is approved, but source revision has changed, setting status to needs review.

Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Change successfully merged at revision efc18399977fbf5e6bd8a6fd2b8d745293b24382

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/.gitignore b/.gitignore
index ca44404..874e257 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,9 @@
1deps/
2__pycache__
3*~
4*.swp1*.swp
2*~
3.coverage
4.pytest_cache/
5.tox/
6.unit-state.db
7__pycache__
5builds/8builds/
9deps/
diff --git a/Makefile b/Makefile
index 6483241..dc50e2b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,21 +1,16 @@
1BUILDDEST:=$(if $(JUJU_REPOSITORY),$(JUJU_REPOSITORY),"../graylog-built")1BUILDDEST:=$(if $(JUJU_REPOSITORY),$(JUJU_REPOSITORY),"../graylog-built")
2BUILTCHARMDIR:="$(BUILDDEST)/builds/graylog"2BUILTCHARMDIR:="$(BUILDDEST)/builds/graylog"
33
4PYTHON_SCRIPTS = \
5 ./actions/actions.py \
6 ./files/check_graylog_health.py \
7 ./lib/graylogapi.py \
8 ./reactive/graylog.py \
9 ./tests/*.py \
10 ./unit_tests/graylog.py
11
12all: unittest4all: unittest
135
14.PHONY: clean6.PHONY: clean
15clean:7clean:
8 @echo "Cleaning files"
16 @rm -f .unit-state.db9 @rm -f .unit-state.db
17 @find . -name "*.pyc" -type f -exec rm -f '{}' \;10 @find . -name "*.pyc" -type f -exec rm -f '{}' \;
18 @find . -name "__pycache__" -type d -prune -exec rm -rf '{}' \;11 @find . -name "__pycache__" -type d -prune -exec rm -rf '{}' \;
12 @rm -rf ./.tox
13 @rm -rf ./.pytest_cache
1914
20.PHONY: sysdeps15.PHONY: sysdeps
21sysdeps:16sysdeps:
@@ -35,12 +30,12 @@ testdeps:
35.PHONY: lint30.PHONY: lint
36lint: sysdeps31lint: sysdeps
37 @echo "Checking Python syntax..."32 @echo "Checking Python syntax..."
38 @flake8 --max-complexity=10 --filename=\* --ignore=E501,E402 $(PYTHON_SCRIPTS) && echo OK33 @tox -e lint
3934
40.PHONY: unittest35.PHONY: unittest
41unittest: sysdeps lint36unittest: sysdeps lint
42 @echo "Running unit tests..."37 @echo "Running unit tests..."
43 nosetests3 unit_tests/*38 @tox -e unit
4439
45.PHONY: charmbuild40.PHONY: charmbuild
46charmbuild:41charmbuild:
diff --git a/config.yaml b/config.yaml
index 451f73f..21e76c6 100644
--- a/config.yaml
+++ b/config.yaml
@@ -88,3 +88,8 @@ options:
88 default: 504488 default: 5044
89 type: int89 type: int
90 description: TCP port for Beats input when relation is joined90 description: TCP port for Beats input when relation is joined
91 jvm_heap_size:
92 default: "1G"
93 type: string
94 description: |
95 JVM Heap memory size (default 1G)
diff --git a/files/check_graylog_health.py b/files/check_graylog_health.py
index 5842727..a349d4a 100755
--- a/files/check_graylog_health.py
+++ b/files/check_graylog_health.py
@@ -11,7 +11,7 @@ libs_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),
11if libs_dir not in sys.path:11if libs_dir not in sys.path:
12 sys.path.append(libs_dir)12 sys.path.append(libs_dir)
1313
14from graylogapi import GraylogAPI14from graylogapi import GraylogAPI # NOQA: E402
1515
16STATE_OK = 016STATE_OK = 0
17STATE_WARNING = 117STATE_WARNING = 1
diff --git a/lib/logextract.py b/lib/logextract.py
index 07e4c6f..2447da4 100644
--- a/lib/logextract.py
+++ b/lib/logextract.py
@@ -4,6 +4,7 @@ extraction
44
5import re5import re
66
7
7class GraylogTitleSourceItems:8class GraylogTitleSourceItems:
89
9 def __init__(self, graylogapi=None):10 def __init__(self, graylogapi=None):
@@ -22,7 +23,7 @@ class GraylogTitleSourceItems:
22 def post(self, title, source):23 def post(self, title, source):
23 return self.graylogapi.request(24 return self.graylogapi.request(
24 self.url, method='POST',25 self.url, method='POST',
25 data={'title' : title, 'source': source})26 data={'title': title, 'source': source})
2627
27 def delete(self, title):28 def delete(self, title):
28 id_ = self.get_for_title(title)29 id_ = self.get_for_title(title)
@@ -44,17 +45,16 @@ class GraylogTitleSourceItems:
44 else:45 else:
45 self.post(title, source)46 self.post(title, source)
4647
47class GraylogPipelines(GraylogTitleSourceItems):
4848
49class GraylogPipelines(GraylogTitleSourceItems):
49 url = '/plugins/org.graylog.plugins.pipelineprocessor/system/pipelines/pipeline'50 url = '/plugins/org.graylog.plugins.pipelineprocessor/system/pipelines/pipeline'
5051
51class GraylogRules(GraylogTitleSourceItems):
5252
53class GraylogRules(GraylogTitleSourceItems):
53 url = '/plugins/org.graylog.plugins.pipelineprocessor/system/pipelines/rule'54 url = '/plugins/org.graylog.plugins.pipelineprocessor/system/pipelines/rule'
5455
5556
56class GraylogStreams:57class GraylogStreams:
57
58 def __init__(self, graylogapi=None):58 def __init__(self, graylogapi=None):
59 self.graylogapi = graylogapi59 self.graylogapi = graylogapi
6060
@@ -85,20 +85,21 @@ class GraylogStreams:
85 if pipeline:85 if pipeline:
86 self.graylogapi.request(url, method="POST",86 self.graylogapi.request(url, method="POST",
87 data={"stream_id": streamid,87 data={"stream_id": streamid,
88 "pipeline_ids" : [pipeline['id']]})88 "pipeline_ids": [pipeline['id']]})
89
9089
9190
92class LogExtractPipelineException(Exception):91class LogExtractPipelineException(Exception):
93 """Error handling log extraction92 """Error handling log extraction
94 """93 """
9594
95
96_logextract_pipe_template = '''96_logextract_pipe_template = '''
97pipeline "{}"97pipeline "{}"
98stage 0 match either98stage 0 match either
99{}99{}
100end'''100end'''
101101
102
102class LogExtractPipeline:103class LogExtractPipeline:
103 """Manage a pipeline with rules for log extraction104 """Manage a pipeline with rules for log extraction
104 The pipeline comprises a single stage which holds105 The pipeline comprises a single stage which holds
@@ -139,4 +140,3 @@ class LogExtractPipeline:
139 pipesrc = _logextract_pipe_template.format(self.title, ''.join(titlerefs))140 pipesrc = _logextract_pipe_template.format(self.title, ''.join(titlerefs))
140 self.pipelines.set(self.title, pipesrc)141 self.pipelines.set(self.title, pipesrc)
141 self.streams.connect_pipeline(self.title, self.all_messages)142 self.streams.connect_pipeline(self.title, self.all_messages)
142
diff --git a/reactive/graylog.py b/reactive/graylog.py
index 0ce774b..c3895ff 100644
--- a/reactive/graylog.py
+++ b/reactive/graylog.py
@@ -18,11 +18,15 @@ if libs_dir not in sys.path:
18 sys.path.append(libs_dir)18 sys.path.append(libs_dir)
1919
20from graylogapi import GraylogAPI # NOQA: E40220from graylogapi import GraylogAPI # NOQA: E402
21import logextract21import logextract # NOQA: E402
2222
23API_PORT = '9001' # This is the default set by the snap23API_PORT = '9001' # This is the default set by the snap
24API_URL = 'http://127.0.0.1:9001/api/' # This is the default set by the snap24API_URL = 'http://127.0.0.1:9001/api/' # This is the default set by the snap
25CONF_FILE = '/var/snap/graylog/common/server.conf'25CONF_FILE = '/var/snap/graylog/common/server.conf'
26# /snap/graylog is a read-only squashfs so we use the initial settings
27# and write out an override to SERVER_DEFAULT_CONF_FILE
28SHIPPED_SNAP_SERVER_DEFAULT_CONF_FILE = '/snap/graylog/current/etc/default/graylog-server'
29SERVER_DEFAULT_CONF_FILE = '/var/snap/graylog/current/default-graylog-server'
26ELASTICSEARCH_DISCOVERY_PORT = '9300'30ELASTICSEARCH_DISCOVERY_PORT = '9300'
27SERVICE_NAME = 'snap.graylog.graylog'31SERVICE_NAME = 'snap.graylog.graylog'
2832
@@ -97,6 +101,8 @@ def configure_graylog():
97 if rules_config and isinstance(rules_config, list):101 if rules_config and isinstance(rules_config, list):
98 _configure_logextraction(rules_config)102 _configure_logextraction(rules_config)
99103
104 set_jvm_heap_size(conf['jvm_heap_size'])
105
100 remove_state('graylog_api.configured')106 remove_state('graylog_api.configured')
101 set_state('graylog.configured')107 set_state('graylog.configured')
102 report_status()108 report_status()
@@ -530,7 +536,7 @@ def set_conf(key, value, conf_path=CONF_FILE):
530 so setting the configuration this way avoids having to regenerate those values.536 so setting the configuration this way avoids having to regenerate those values.
531 """537 """
532 conf = []538 conf = []
533 key_re = re.compile('^#*\s*{}'.format(key))539 key_re = re.compile('^#*\\s*{}'.format(key))
534540
535 changed = False541 changed = False
536 replaced = False542 replaced = False
@@ -563,6 +569,64 @@ def set_conf(key, value, conf_path=CONF_FILE):
563 with open(conf_path, 'wb') as conf_file:569 with open(conf_path, 'wb') as conf_file:
564 conf_file.write('\n'.join(conf).encode())570 conf_file.write('\n'.join(conf).encode())
565 return True571 return True
572
573 return False
574
575
576def parse_java_opts(opts, size):
577 foundXms = False
578 foundXmx = False
579 new_opts = []
580 for opt in opts.split():
581 if opt.startswith('-Xms'):
582 foundXms = True
583 if size == '':
584 continue
585 new_opts.append('-Xms{}'.format(size))
586 elif opt.startswith('-Xmx'):
587 foundXmx = True
588 if size == '':
589 continue
590 new_opts.append('-Xmx{}'.format(size))
591 else:
592 new_opts.append(opt)
593 if not foundXms:
594 new_opts.append('-Xms{}'.format(size))
595 if not foundXmx:
596 new_opts.append('-Xmx{}'.format(size))
597 return new_opts
598
599
600def set_jvm_heap_size(heap_size='1G', conf_path=SERVER_DEFAULT_CONF_FILE):
601 size = heap_size.lower()
602 conf = []
603 key_re = re.compile('^\\s*GRAYLOG_SERVER_JAVA_OPTS\\s*="(.*)"$')
604 changed = False
605 # If specified /etc/default/graylog-server doesn't exist, use the default
606 # file shipped out by the snap
607 if not os.path.exists(conf_path):
608 updated_conf_path = SHIPPED_SNAP_SERVER_DEFAULT_CONF_FILE
609 else:
610 updated_conf_path = conf_path
611 with open(updated_conf_path, 'rb') as conf_file:
612 for line in conf_file:
613 line = line.decode()
614 m = key_re.match(line)
615 if not m:
616 conf.append(line)
617 continue
618 new_opts = parse_java_opts(m.group(1), size)
619 new_line = 'GRAYLOG_SERVER_JAVA_OPTS="{}"\n'.format(' '.join(new_opts))
620 if new_line != line:
621 hookenv.log('Updating GRAYLOG_SERVER_JAVA_OPTS="{}".'.format(''.join(new_opts)))
622 changed = True
623 conf.append(new_line)
624
625 if changed:
626 set_state('graylog.needs_restart')
627 with open(conf_path, 'wb') as conf_file:
628 conf_file.write(''.join(conf).encode())
629 return True
566 return False630 return False
567631
568632
@@ -586,7 +650,7 @@ def configure_nagios(nagios):
586 if conf['web_listen_uri']:650 if conf['web_listen_uri']:
587 url = urlparse(conf['web_listen_uri'])651 url = urlparse(conf['web_listen_uri'])
588 # LP:#1706265: Work around this bug by escaping some characters.652 # LP:#1706265: Work around this bug by escaping some characters.
589 check_string = '\<title\>Graylog\ Web\ Interface\</title\>'653 check_string = '\\<title\\>Graylog\\ Web\\ Interface\\</title\\>'
590 url_path = url.path654 url_path = url.path
591 # Catch URI without an explicit path655 # Catch URI without an explicit path
592 if not url_path:656 if not url_path:
@@ -597,7 +661,8 @@ def configure_nagios(nagios):
597 nrpe_setup.add_check(661 nrpe_setup.add_check(
598 'graylog_http',662 'graylog_http',
599 'Graylog Web UI check',663 'Graylog Web UI check',
600 '/usr/lib/nagios/plugins/check_http -I {} -p {} -u "{}" -s "{}"'.format(url.hostname, str(url.port), url_path, check_string)664 '/usr/lib/nagios/plugins/check_http -I {} -p {} -u "{}" -s "{}"'
665 .format(url.hostname, str(url.port), url_path, check_string)
601 )666 )
602 check_string = 'cluster_id'667 check_string = 'cluster_id'
603 nrpe_setup.add_check(668 nrpe_setup.add_check(
diff --git a/requirements.txt b/requirements.txt
604new file mode 100644669new file mode 100644
index 0000000..8462291
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1 @@
1# Include python requirements here
diff --git a/tox.ini b/tox.ini
0new file mode 1006442new file mode 100644
index 0000000..1cdd9ba
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,27 @@
1[tox]
2skipsdist=True
3envlist = unit
4skip_missing_interpreters = True
5
6[testenv]
7basepython = python3
8setenv =
9 PYTHONPATH = .
10
11[testenv:unit]
12commands = pytest -v --ignore {toxinidir}/tests --cov=lib --cov=reactive --cov=actions --cov-report=term-missing --cov-branch
13deps = -r{toxinidir}/unit_tests/requirements.txt
14 -r{toxinidir}/requirements.txt
15setenv = PYTHONPATH={toxinidir}/lib
16
17[testenv:lint]
18commands = flake8
19deps = flake8
20
21[flake8]
22exclude =
23 .git,
24 __pycache__,
25 .tox,
26max-line-length = 120
27max-complexity = 10
diff --git a/unit_tests/requirements.txt b/unit_tests/requirements.txt
0new file mode 10064428new file mode 100644
index 0000000..29f9318
--- /dev/null
+++ b/unit_tests/requirements.txt
@@ -0,0 +1,6 @@
1charmhelpers
2charms.reactive
3mock
4pytest
5pytest-cov
6requests
diff --git a/unit_tests/graylog.py b/unit_tests/test_graylog.py
0similarity index 75%7similarity index 75%
1rename from unit_tests/graylog.py8rename from unit_tests/graylog.py
2rename to unit_tests/test_graylog.py9rename to unit_tests/test_graylog.py
index 3394201..79cdaf0 100644
--- a/unit_tests/graylog.py
+++ b/unit_tests/test_graylog.py
@@ -8,9 +8,10 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
88
9from reactive.graylog import (9from reactive.graylog import (
10 set_conf,10 set_conf,
11 _check_input_exists)11 set_jvm_heap_size,
12from lib.graylogapi import GraylogAPI12 _check_input_exists) # NOQA: E402
13from files import check_graylog_health13from lib.graylogapi import GraylogAPI # NOQA: E402
14from files import check_graylog_health # NOQA: E402
1415
15initial_conf = u"""#key1 = value116initial_conf = u"""#key1 = value1
16key2 = value217key2 = value2
@@ -173,3 +174,93 @@ class TestHealthCheck(unittest.TestCase):
173 'uncommitted_journal_entries': ucommitted}174 'uncommitted_journal_entries': ucommitted}
174 state, _ = check_graylog_health.journal_state(mock_api, args)175 state, _ = check_graylog_health.journal_state(mock_api, args)
175 self.assertEqual(state, exp_state)176 self.assertEqual(state, exp_state)
177
178
179etc_default_conf = u"""
180# Path to the java executable.
181JAVA=/usr/bin/java
182
183# Default Java options for heap and garbage collection.
184{}
185
186# Pass some extra args to graylog-server. (i.e. "-d" to enable debug mode)
187GRAYLOG_SERVER_ARGS=""
188
189# Program that will be used to wrap the graylog-server command. Useful to
190# support programs like authbind.
191GRAYLOG_COMMAND_WRAPPER=""
192"""
193
194heap_default = u"""
195GRAYLOG_SERVER_JAVA_OPTS="-Xms1g -Xmx1g -XX:NewRatio=1 -server -XX:+ResizeTLAB -XX:+UseConcMarkSweepGC \
196-XX:+CMSConcurrentMTEnabled -XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC -XX:-OmitStackTraceInFastThrow"
197"""
198
199heap_2g = u"""
200GRAYLOG_SERVER_JAVA_OPTS="-Xms2g -Xmx2g -XX:NewRatio=1 -server -XX:+ResizeTLAB -XX:+UseConcMarkSweepGC \
201-XX:+CMSConcurrentMTEnabled -XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC -XX:-OmitStackTraceInFastThrow"
202"""
203
204heap_not_present = u"""
205GRAYLOG_SERVER_JAVA_OPTS="-XX:NewRatio=1 -server -XX:+ResizeTLAB -XX:+UseConcMarkSweepGC -XX:+CMSConcurrentMTEnabled \
206-XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC -XX:-OmitStackTraceInFastThrow -Xms4g -Xmx4g"
207"""
208
209heap_unset = u"""
210GRAYLOG_SERVER_JAVA_OPTS="-XX:NewRatio=1 -server -XX:+ResizeTLAB -XX:+UseConcMarkSweepGC -XX:+CMSConcurrentMTEnabled \
211-XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC -XX:-OmitStackTraceInFastThrow"
212"""
213
214heap_not_present = u"""
215GRAYLOG_SERVER_JAVA_OPTS="-XX:NewRatio=1 -server -XX:+ResizeTLAB -XX:+UseConcMarkSweepGC -XX:+CMSConcurrentMTEnabled \
216-XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC -XX:-OmitStackTraceInFastThrow -Xms4g -Xmx4g"
217"""
218
219heap_twice = u"""
220GRAYLOG_SERVER_JAVA_OPTS="-XX:NewRatio=1 -server -XX:+ResizeTLAB -XX:+UseConcMarkSweepGC -XX:+CMSConcurrentMTEnabled \
221-XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC -XX:-OmitStackTraceInFastThrow -Xms8g -Xmx8g"
222"""
223
224
225class TestSetJVMHeapSize(unittest.TestCase):
226
227 def setUp(self):
228 temp_file = tempfile.NamedTemporaryFile(delete=False)
229 temp_file.write(etc_default_conf.format(heap_default).encode())
230 temp_file.close()
231 self.conf_file = temp_file.name
232
233 def tearDown(self):
234 os.remove(self.conf_file)
235
236 def conf_equals(self, want):
237 with open(self.conf_file, 'r') as conf:
238 got = conf.read()
239 if got == want:
240 return True
241 print('{}\n--- != ---\n{}'.format(got, want))
242 return False
243
244 def test_same(self):
245 set_jvm_heap_size('1g', self.conf_file)
246 self.assertTrue(self.conf_equals(etc_default_conf.format(heap_default)))
247
248 def test_update(self):
249 set_jvm_heap_size('2g', self.conf_file)
250 self.assertTrue(self.conf_equals(etc_default_conf.format(heap_2g)))
251
252 def test_unset(self):
253 # Remove Xms and Xmx
254 set_jvm_heap_size('', self.conf_file)
255 self.assertTrue(self.conf_equals(etc_default_conf.format(heap_unset)))
256
257 def test_add(self):
258 set_jvm_heap_size('', self.conf_file)
259 set_jvm_heap_size('4g', self.conf_file)
260 self.assertTrue(self.conf_equals(etc_default_conf.format(heap_not_present)))
261
262 def test_add_twice(self):
263 set_jvm_heap_size('', self.conf_file)
264 set_jvm_heap_size('6g', self.conf_file)
265 set_jvm_heap_size('8g', self.conf_file)
266 self.assertTrue(self.conf_equals(etc_default_conf.format(heap_twice)))
diff --git a/unit_tests/test_logextract.py b/unit_tests/test_logextract.py
index fd04bf1..69d87d8 100644
--- a/unit_tests/test_logextract.py
+++ b/unit_tests/test_logextract.py
@@ -2,20 +2,19 @@ import unittest
2from unittest import mock2from unittest import mock
33
4from lib import logextract4from lib import logextract
5from lib.graylogapi import GraylogAPI
65
76
8testdata_simple_pipeline_source = '\npipeline "testpipe"\nstage 1 match either\n rule "test-rule";\nend\n'7testdata_simple_pipeline_source = '\npipeline "testpipe"\nstage 1 match either\n rule "test-rule";\nend\n'
98
10testdata_simple_pipeline = [{'description': None, 'stages':9testdata_simple_pipeline = [{'description': None, 'stages':
11 [{'match_all': False, 'rules':10 [{'match_all': False, 'rules':
12 ['test-rule'], 'stage': 1}],11 ['test-rule'], 'stage': 1}],
13 'source': testdata_simple_pipeline_source,12 'source': testdata_simple_pipeline_source,
14 'created_at': '2018-06-18T14:49:27.427Z',13 'created_at': '2018-06-18T14:49:27.427Z',
15 'modified_at': '2018-06-18T14:49:27.427Z',14 'modified_at': '2018-06-18T14:49:27.427Z',
16 'id': '5b27c6778ac7b4647301a562',15 'id': '5b27c6778ac7b4647301a562',
17 'errors': None,16 'errors': None,
18 'title': 'juju-logextract-pipeline'}]17 'title': 'juju-logextract-pipeline'}]
1918
20testdata_streams = {'total': 1,19testdata_streams = {'total': 1,
21 'streams': [20 'streams': [
@@ -30,18 +29,19 @@ testdata_rules = [
30 {29 {
31 "title": "from ceph mon",30 "title": "from ceph mon",
32 "description": "",31 "description": "",
33 "source": "rule \"from ceph mon\"\nwhen\n has_field(\"logdir\") && $message.logdir == \"ceph\" && regex(\"^ceph-mon\", to_string($message.juju_principal_unit)).matches == true\nthen\n set_field(\"subsystem\", \"ceph-mon\");\nend;\n",32 "source": "rule \"from ceph mon\"\nwhen\n has_field(\"logdir\") && $message.logdir == \"ceph\" && regex(\"^ceph-mon\", to_string($message.juju_principal_unit)).matches == true\nthen\n set_field(\"subsystem\", \"ceph-mon\");\nend;\n", # NOQA: E501
34 "created_at": "2018-06-17T14:32:13.632Z",33 "created_at": "2018-06-17T14:32:13.632Z",
35 "modified_at": "2018-06-17T14:42:25.818Z",34 "modified_at": "2018-06-17T14:42:25.818Z",
36 "errors": None,35 "errors": None,
37 "id": "5b2670ed6140b943aef99ae9"36 "id": "5b2670ed6140b943aef99ae9"
38 },]37 }]
3938
40testdata_stream_connect = {39testdata_stream_connect = {
41 "stream_id": "000000000000000000000001",40 "stream_id": "000000000000000000000001",
42 "pipeline_ids" : ["5b35061c6140b943ae096769"]41 "pipeline_ids": ["5b35061c6140b943ae096769"]
43}42}
4443
44
45class TestGraylogPipelines(unittest.TestCase):45class TestGraylogPipelines(unittest.TestCase):
4646
47 @mock.patch('lib.graylogapi.GraylogAPI')47 @mock.patch('lib.graylogapi.GraylogAPI')
@@ -69,7 +69,6 @@ class TestGraylogRules(unittest.TestCase):
69 self.assertEqual(rules[0]['title'], "from ceph mon")69 self.assertEqual(rules[0]['title'], "from ceph mon")
7070
7171
72
73class TestGraylogStreams(unittest.TestCase):72class TestGraylogStreams(unittest.TestCase):
7473
75 @mock.patch('lib.graylogapi.GraylogAPI')74 @mock.patch('lib.graylogapi.GraylogAPI')
@@ -77,18 +76,16 @@ class TestGraylogStreams(unittest.TestCase):
77 mock_api.request.return_value = testdata_streams76 mock_api.request.return_value = testdata_streams
78 gstreams = logextract.GraylogStreams(mock_api)77 gstreams = logextract.GraylogStreams(mock_api)
79 allmsgs = gstreams.get_stream_id_for("All messages")78 allmsgs = gstreams.get_stream_id_for("All messages")
80 self.assertEqual(allmsgs,79 self.assertEqual(allmsgs, testdata_streams['streams'][0]['id'])
81 testdata_streams['streams'][0]['id'])
82 nope = gstreams.get_stream_id_for("I don't exist")80 nope = gstreams.get_stream_id_for("I don't exist")
83 self.assertIsNone(nope)81 self.assertIsNone(nope)
8482
83
85class TestLogExtractPipeline(unittest.TestCase):84class TestLogExtractPipeline(unittest.TestCase):
8685
87 @mock.patch('lib.graylogapi.GraylogAPI')86 @mock.patch('lib.graylogapi.GraylogAPI')
88 def test_get_rules(self, mock_api):87 def test_get_rules(self, mock_api):
89 mock_api.request.return_value = testdata_simple_pipeline88 mock_api.request.return_value = testdata_simple_pipeline
90 logext = logextract.LogExtractPipeline(mock_api)
91 rules = logext.get_rules()
9289
93 def test_parse_rule_title(self):90 def test_parse_rule_title(self):
94 logext = logextract.LogExtractPipeline()91 logext = logextract.LogExtractPipeline()

Subscribers

People subscribed via source and target branches

to all changes: