Merge ~hloeung/charm-graylog:master into ~graylog-charmers/charm-graylog:master
- Git
- lp:~hloeung/charm-graylog
- master
- Merge into 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) |
||||
Related bugs: |
|
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
Description of the change
To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : | # |
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 efc18399977fbf5
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/.gitignore b/.gitignore | |||
2 | index ca44404..874e257 100644 | |||
3 | --- a/.gitignore | |||
4 | +++ b/.gitignore | |||
5 | @@ -1,5 +1,9 @@ | |||
6 | 1 | deps/ | ||
7 | 2 | __pycache__ | ||
8 | 3 | *~ | ||
9 | 4 | *.swp | 1 | *.swp |
10 | 2 | *~ | ||
11 | 3 | .coverage | ||
12 | 4 | .pytest_cache/ | ||
13 | 5 | .tox/ | ||
14 | 6 | .unit-state.db | ||
15 | 7 | __pycache__ | ||
16 | 5 | builds/ | 8 | builds/ |
17 | 9 | deps/ | ||
18 | diff --git a/Makefile b/Makefile | |||
19 | index 6483241..dc50e2b 100644 | |||
20 | --- a/Makefile | |||
21 | +++ b/Makefile | |||
22 | @@ -1,21 +1,16 @@ | |||
23 | 1 | BUILDDEST:=$(if $(JUJU_REPOSITORY),$(JUJU_REPOSITORY),"../graylog-built") | 1 | BUILDDEST:=$(if $(JUJU_REPOSITORY),$(JUJU_REPOSITORY),"../graylog-built") |
24 | 2 | BUILTCHARMDIR:="$(BUILDDEST)/builds/graylog" | 2 | BUILTCHARMDIR:="$(BUILDDEST)/builds/graylog" |
25 | 3 | 3 | ||
26 | 4 | PYTHON_SCRIPTS = \ | ||
27 | 5 | ./actions/actions.py \ | ||
28 | 6 | ./files/check_graylog_health.py \ | ||
29 | 7 | ./lib/graylogapi.py \ | ||
30 | 8 | ./reactive/graylog.py \ | ||
31 | 9 | ./tests/*.py \ | ||
32 | 10 | ./unit_tests/graylog.py | ||
33 | 11 | |||
34 | 12 | all: unittest | 4 | all: unittest |
35 | 13 | 5 | ||
36 | 14 | .PHONY: clean | 6 | .PHONY: clean |
37 | 15 | clean: | 7 | clean: |
38 | 8 | @echo "Cleaning files" | ||
39 | 16 | @rm -f .unit-state.db | 9 | @rm -f .unit-state.db |
40 | 17 | @find . -name "*.pyc" -type f -exec rm -f '{}' \; | 10 | @find . -name "*.pyc" -type f -exec rm -f '{}' \; |
41 | 18 | @find . -name "__pycache__" -type d -prune -exec rm -rf '{}' \; | 11 | @find . -name "__pycache__" -type d -prune -exec rm -rf '{}' \; |
42 | 12 | @rm -rf ./.tox | ||
43 | 13 | @rm -rf ./.pytest_cache | ||
44 | 19 | 14 | ||
45 | 20 | .PHONY: sysdeps | 15 | .PHONY: sysdeps |
46 | 21 | sysdeps: | 16 | sysdeps: |
47 | @@ -35,12 +30,12 @@ testdeps: | |||
48 | 35 | .PHONY: lint | 30 | .PHONY: lint |
49 | 36 | lint: sysdeps | 31 | lint: sysdeps |
50 | 37 | @echo "Checking Python syntax..." | 32 | @echo "Checking Python syntax..." |
52 | 38 | @flake8 --max-complexity=10 --filename=\* --ignore=E501,E402 $(PYTHON_SCRIPTS) && echo OK | 33 | @tox -e lint |
53 | 39 | 34 | ||
54 | 40 | .PHONY: unittest | 35 | .PHONY: unittest |
55 | 41 | unittest: sysdeps lint | 36 | unittest: sysdeps lint |
56 | 42 | @echo "Running unit tests..." | 37 | @echo "Running unit tests..." |
58 | 43 | nosetests3 unit_tests/* | 38 | @tox -e unit |
59 | 44 | 39 | ||
60 | 45 | .PHONY: charmbuild | 40 | .PHONY: charmbuild |
61 | 46 | charmbuild: | 41 | charmbuild: |
62 | diff --git a/config.yaml b/config.yaml | |||
63 | index 451f73f..21e76c6 100644 | |||
64 | --- a/config.yaml | |||
65 | +++ b/config.yaml | |||
66 | @@ -88,3 +88,8 @@ options: | |||
67 | 88 | default: 5044 | 88 | default: 5044 |
68 | 89 | type: int | 89 | type: int |
69 | 90 | description: TCP port for Beats input when relation is joined | 90 | description: TCP port for Beats input when relation is joined |
70 | 91 | jvm_heap_size: | ||
71 | 92 | default: "1G" | ||
72 | 93 | type: string | ||
73 | 94 | description: | | ||
74 | 95 | JVM Heap memory size (default 1G) | ||
75 | diff --git a/files/check_graylog_health.py b/files/check_graylog_health.py | |||
76 | index 5842727..a349d4a 100755 | |||
77 | --- a/files/check_graylog_health.py | |||
78 | +++ b/files/check_graylog_health.py | |||
79 | @@ -11,7 +11,7 @@ libs_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), | |||
80 | 11 | if libs_dir not in sys.path: | 11 | if libs_dir not in sys.path: |
81 | 12 | sys.path.append(libs_dir) | 12 | sys.path.append(libs_dir) |
82 | 13 | 13 | ||
84 | 14 | from graylogapi import GraylogAPI | 14 | from graylogapi import GraylogAPI # NOQA: E402 |
85 | 15 | 15 | ||
86 | 16 | STATE_OK = 0 | 16 | STATE_OK = 0 |
87 | 17 | STATE_WARNING = 1 | 17 | STATE_WARNING = 1 |
88 | diff --git a/lib/logextract.py b/lib/logextract.py | |||
89 | index 07e4c6f..2447da4 100644 | |||
90 | --- a/lib/logextract.py | |||
91 | +++ b/lib/logextract.py | |||
92 | @@ -4,6 +4,7 @@ extraction | |||
93 | 4 | 4 | ||
94 | 5 | import re | 5 | import re |
95 | 6 | 6 | ||
96 | 7 | |||
97 | 7 | class GraylogTitleSourceItems: | 8 | class GraylogTitleSourceItems: |
98 | 8 | 9 | ||
99 | 9 | def __init__(self, graylogapi=None): | 10 | def __init__(self, graylogapi=None): |
100 | @@ -22,7 +23,7 @@ class GraylogTitleSourceItems: | |||
101 | 22 | def post(self, title, source): | 23 | def post(self, title, source): |
102 | 23 | return self.graylogapi.request( | 24 | return self.graylogapi.request( |
103 | 24 | self.url, method='POST', | 25 | self.url, method='POST', |
105 | 25 | data={'title' : title, 'source': source}) | 26 | data={'title': title, 'source': source}) |
106 | 26 | 27 | ||
107 | 27 | def delete(self, title): | 28 | def delete(self, title): |
108 | 28 | id_ = self.get_for_title(title) | 29 | id_ = self.get_for_title(title) |
109 | @@ -44,17 +45,16 @@ class GraylogTitleSourceItems: | |||
110 | 44 | else: | 45 | else: |
111 | 45 | self.post(title, source) | 46 | self.post(title, source) |
112 | 46 | 47 | ||
113 | 47 | class GraylogPipelines(GraylogTitleSourceItems): | ||
114 | 48 | 48 | ||
115 | 49 | class GraylogPipelines(GraylogTitleSourceItems): | ||
116 | 49 | url = '/plugins/org.graylog.plugins.pipelineprocessor/system/pipelines/pipeline' | 50 | url = '/plugins/org.graylog.plugins.pipelineprocessor/system/pipelines/pipeline' |
117 | 50 | 51 | ||
118 | 51 | class GraylogRules(GraylogTitleSourceItems): | ||
119 | 52 | 52 | ||
120 | 53 | class GraylogRules(GraylogTitleSourceItems): | ||
121 | 53 | url = '/plugins/org.graylog.plugins.pipelineprocessor/system/pipelines/rule' | 54 | url = '/plugins/org.graylog.plugins.pipelineprocessor/system/pipelines/rule' |
122 | 54 | 55 | ||
123 | 55 | 56 | ||
124 | 56 | class GraylogStreams: | 57 | class GraylogStreams: |
125 | 57 | |||
126 | 58 | def __init__(self, graylogapi=None): | 58 | def __init__(self, graylogapi=None): |
127 | 59 | self.graylogapi = graylogapi | 59 | self.graylogapi = graylogapi |
128 | 60 | 60 | ||
129 | @@ -85,20 +85,21 @@ class GraylogStreams: | |||
130 | 85 | if pipeline: | 85 | if pipeline: |
131 | 86 | self.graylogapi.request(url, method="POST", | 86 | self.graylogapi.request(url, method="POST", |
132 | 87 | data={"stream_id": streamid, | 87 | data={"stream_id": streamid, |
135 | 88 | "pipeline_ids" : [pipeline['id']]}) | 88 | "pipeline_ids": [pipeline['id']]}) |
134 | 89 | |||
136 | 90 | 89 | ||
137 | 91 | 90 | ||
138 | 92 | class LogExtractPipelineException(Exception): | 91 | class LogExtractPipelineException(Exception): |
139 | 93 | """Error handling log extraction | 92 | """Error handling log extraction |
140 | 94 | """ | 93 | """ |
141 | 95 | 94 | ||
142 | 95 | |||
143 | 96 | _logextract_pipe_template = ''' | 96 | _logextract_pipe_template = ''' |
144 | 97 | pipeline "{}" | 97 | pipeline "{}" |
145 | 98 | stage 0 match either | 98 | stage 0 match either |
146 | 99 | {} | 99 | {} |
147 | 100 | end''' | 100 | end''' |
148 | 101 | 101 | ||
149 | 102 | |||
150 | 102 | class LogExtractPipeline: | 103 | class LogExtractPipeline: |
151 | 103 | """Manage a pipeline with rules for log extraction | 104 | """Manage a pipeline with rules for log extraction |
152 | 104 | The pipeline comprises a single stage which holds | 105 | The pipeline comprises a single stage which holds |
153 | @@ -139,4 +140,3 @@ class LogExtractPipeline: | |||
154 | 139 | pipesrc = _logextract_pipe_template.format(self.title, ''.join(titlerefs)) | 140 | pipesrc = _logextract_pipe_template.format(self.title, ''.join(titlerefs)) |
155 | 140 | self.pipelines.set(self.title, pipesrc) | 141 | self.pipelines.set(self.title, pipesrc) |
156 | 141 | self.streams.connect_pipeline(self.title, self.all_messages) | 142 | self.streams.connect_pipeline(self.title, self.all_messages) |
157 | 142 | |||
158 | diff --git a/reactive/graylog.py b/reactive/graylog.py | |||
159 | index 0ce774b..c3895ff 100644 | |||
160 | --- a/reactive/graylog.py | |||
161 | +++ b/reactive/graylog.py | |||
162 | @@ -18,11 +18,15 @@ if libs_dir not in sys.path: | |||
163 | 18 | sys.path.append(libs_dir) | 18 | sys.path.append(libs_dir) |
164 | 19 | 19 | ||
165 | 20 | from graylogapi import GraylogAPI # NOQA: E402 | 20 | from graylogapi import GraylogAPI # NOQA: E402 |
167 | 21 | import logextract | 21 | import logextract # NOQA: E402 |
168 | 22 | 22 | ||
169 | 23 | API_PORT = '9001' # This is the default set by the snap | 23 | API_PORT = '9001' # This is the default set by the snap |
170 | 24 | API_URL = 'http://127.0.0.1:9001/api/' # This is the default set by the snap | 24 | API_URL = 'http://127.0.0.1:9001/api/' # This is the default set by the snap |
171 | 25 | CONF_FILE = '/var/snap/graylog/common/server.conf' | 25 | CONF_FILE = '/var/snap/graylog/common/server.conf' |
172 | 26 | # /snap/graylog is a read-only squashfs so we use the initial settings | ||
173 | 27 | # and write out an override to SERVER_DEFAULT_CONF_FILE | ||
174 | 28 | SHIPPED_SNAP_SERVER_DEFAULT_CONF_FILE = '/snap/graylog/current/etc/default/graylog-server' | ||
175 | 29 | SERVER_DEFAULT_CONF_FILE = '/var/snap/graylog/current/default-graylog-server' | ||
176 | 26 | ELASTICSEARCH_DISCOVERY_PORT = '9300' | 30 | ELASTICSEARCH_DISCOVERY_PORT = '9300' |
177 | 27 | SERVICE_NAME = 'snap.graylog.graylog' | 31 | SERVICE_NAME = 'snap.graylog.graylog' |
178 | 28 | 32 | ||
179 | @@ -97,6 +101,8 @@ def configure_graylog(): | |||
180 | 97 | if rules_config and isinstance(rules_config, list): | 101 | if rules_config and isinstance(rules_config, list): |
181 | 98 | _configure_logextraction(rules_config) | 102 | _configure_logextraction(rules_config) |
182 | 99 | 103 | ||
183 | 104 | set_jvm_heap_size(conf['jvm_heap_size']) | ||
184 | 105 | |||
185 | 100 | remove_state('graylog_api.configured') | 106 | remove_state('graylog_api.configured') |
186 | 101 | set_state('graylog.configured') | 107 | set_state('graylog.configured') |
187 | 102 | report_status() | 108 | report_status() |
188 | @@ -530,7 +536,7 @@ def set_conf(key, value, conf_path=CONF_FILE): | |||
189 | 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. |
190 | 531 | """ | 537 | """ |
191 | 532 | conf = [] | 538 | conf = [] |
193 | 533 | key_re = re.compile('^#*\s*{}'.format(key)) | 539 | key_re = re.compile('^#*\\s*{}'.format(key)) |
194 | 534 | 540 | ||
195 | 535 | changed = False | 541 | changed = False |
196 | 536 | replaced = False | 542 | replaced = False |
197 | @@ -563,6 +569,64 @@ def set_conf(key, value, conf_path=CONF_FILE): | |||
198 | 563 | with open(conf_path, 'wb') as conf_file: | 569 | with open(conf_path, 'wb') as conf_file: |
199 | 564 | conf_file.write('\n'.join(conf).encode()) | 570 | conf_file.write('\n'.join(conf).encode()) |
200 | 565 | return True | 571 | return True |
201 | 572 | |||
202 | 573 | return False | ||
203 | 574 | |||
204 | 575 | |||
205 | 576 | def parse_java_opts(opts, size): | ||
206 | 577 | foundXms = False | ||
207 | 578 | foundXmx = False | ||
208 | 579 | new_opts = [] | ||
209 | 580 | for opt in opts.split(): | ||
210 | 581 | if opt.startswith('-Xms'): | ||
211 | 582 | foundXms = True | ||
212 | 583 | if size == '': | ||
213 | 584 | continue | ||
214 | 585 | new_opts.append('-Xms{}'.format(size)) | ||
215 | 586 | elif opt.startswith('-Xmx'): | ||
216 | 587 | foundXmx = True | ||
217 | 588 | if size == '': | ||
218 | 589 | continue | ||
219 | 590 | new_opts.append('-Xmx{}'.format(size)) | ||
220 | 591 | else: | ||
221 | 592 | new_opts.append(opt) | ||
222 | 593 | if not foundXms: | ||
223 | 594 | new_opts.append('-Xms{}'.format(size)) | ||
224 | 595 | if not foundXmx: | ||
225 | 596 | new_opts.append('-Xmx{}'.format(size)) | ||
226 | 597 | return new_opts | ||
227 | 598 | |||
228 | 599 | |||
229 | 600 | def set_jvm_heap_size(heap_size='1G', conf_path=SERVER_DEFAULT_CONF_FILE): | ||
230 | 601 | size = heap_size.lower() | ||
231 | 602 | conf = [] | ||
232 | 603 | key_re = re.compile('^\\s*GRAYLOG_SERVER_JAVA_OPTS\\s*="(.*)"$') | ||
233 | 604 | changed = False | ||
234 | 605 | # If specified /etc/default/graylog-server doesn't exist, use the default | ||
235 | 606 | # file shipped out by the snap | ||
236 | 607 | if not os.path.exists(conf_path): | ||
237 | 608 | updated_conf_path = SHIPPED_SNAP_SERVER_DEFAULT_CONF_FILE | ||
238 | 609 | else: | ||
239 | 610 | updated_conf_path = conf_path | ||
240 | 611 | with open(updated_conf_path, 'rb') as conf_file: | ||
241 | 612 | for line in conf_file: | ||
242 | 613 | line = line.decode() | ||
243 | 614 | m = key_re.match(line) | ||
244 | 615 | if not m: | ||
245 | 616 | conf.append(line) | ||
246 | 617 | continue | ||
247 | 618 | new_opts = parse_java_opts(m.group(1), size) | ||
248 | 619 | new_line = 'GRAYLOG_SERVER_JAVA_OPTS="{}"\n'.format(' '.join(new_opts)) | ||
249 | 620 | if new_line != line: | ||
250 | 621 | hookenv.log('Updating GRAYLOG_SERVER_JAVA_OPTS="{}".'.format(''.join(new_opts))) | ||
251 | 622 | changed = True | ||
252 | 623 | conf.append(new_line) | ||
253 | 624 | |||
254 | 625 | if changed: | ||
255 | 626 | set_state('graylog.needs_restart') | ||
256 | 627 | with open(conf_path, 'wb') as conf_file: | ||
257 | 628 | conf_file.write(''.join(conf).encode()) | ||
258 | 629 | return True | ||
259 | 566 | return False | 630 | return False |
260 | 567 | 631 | ||
261 | 568 | 632 | ||
262 | @@ -586,7 +650,7 @@ def configure_nagios(nagios): | |||
263 | 586 | if conf['web_listen_uri']: | 650 | if conf['web_listen_uri']: |
264 | 587 | url = urlparse(conf['web_listen_uri']) | 651 | url = urlparse(conf['web_listen_uri']) |
265 | 588 | # LP:#1706265: Work around this bug by escaping some characters. | 652 | # LP:#1706265: Work around this bug by escaping some characters. |
267 | 589 | check_string = '\<title\>Graylog\ Web\ Interface\</title\>' | 653 | check_string = '\\<title\\>Graylog\\ Web\\ Interface\\</title\\>' |
268 | 590 | url_path = url.path | 654 | url_path = url.path |
269 | 591 | # Catch URI without an explicit path | 655 | # Catch URI without an explicit path |
270 | 592 | if not url_path: | 656 | if not url_path: |
271 | @@ -597,7 +661,8 @@ def configure_nagios(nagios): | |||
272 | 597 | nrpe_setup.add_check( | 661 | nrpe_setup.add_check( |
273 | 598 | 'graylog_http', | 662 | 'graylog_http', |
274 | 599 | 'Graylog Web UI check', | 663 | 'Graylog Web UI check', |
276 | 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 "{}"' |
277 | 665 | .format(url.hostname, str(url.port), url_path, check_string) | ||
278 | 601 | ) | 666 | ) |
279 | 602 | check_string = 'cluster_id' | 667 | check_string = 'cluster_id' |
280 | 603 | nrpe_setup.add_check( | 668 | nrpe_setup.add_check( |
281 | diff --git a/requirements.txt b/requirements.txt | |||
282 | 604 | new file mode 100644 | 669 | new file mode 100644 |
283 | index 0000000..8462291 | |||
284 | --- /dev/null | |||
285 | +++ b/requirements.txt | |||
286 | @@ -0,0 +1 @@ | |||
287 | 1 | # Include python requirements here | ||
288 | diff --git a/tox.ini b/tox.ini | |||
289 | 0 | new file mode 100644 | 2 | new file mode 100644 |
290 | index 0000000..1cdd9ba | |||
291 | --- /dev/null | |||
292 | +++ b/tox.ini | |||
293 | @@ -0,0 +1,27 @@ | |||
294 | 1 | [tox] | ||
295 | 2 | skipsdist=True | ||
296 | 3 | envlist = unit | ||
297 | 4 | skip_missing_interpreters = True | ||
298 | 5 | |||
299 | 6 | [testenv] | ||
300 | 7 | basepython = python3 | ||
301 | 8 | setenv = | ||
302 | 9 | PYTHONPATH = . | ||
303 | 10 | |||
304 | 11 | [testenv:unit] | ||
305 | 12 | commands = pytest -v --ignore {toxinidir}/tests --cov=lib --cov=reactive --cov=actions --cov-report=term-missing --cov-branch | ||
306 | 13 | deps = -r{toxinidir}/unit_tests/requirements.txt | ||
307 | 14 | -r{toxinidir}/requirements.txt | ||
308 | 15 | setenv = PYTHONPATH={toxinidir}/lib | ||
309 | 16 | |||
310 | 17 | [testenv:lint] | ||
311 | 18 | commands = flake8 | ||
312 | 19 | deps = flake8 | ||
313 | 20 | |||
314 | 21 | [flake8] | ||
315 | 22 | exclude = | ||
316 | 23 | .git, | ||
317 | 24 | __pycache__, | ||
318 | 25 | .tox, | ||
319 | 26 | max-line-length = 120 | ||
320 | 27 | max-complexity = 10 | ||
321 | diff --git a/unit_tests/requirements.txt b/unit_tests/requirements.txt | |||
322 | 0 | new file mode 100644 | 28 | new file mode 100644 |
323 | index 0000000..29f9318 | |||
324 | --- /dev/null | |||
325 | +++ b/unit_tests/requirements.txt | |||
326 | @@ -0,0 +1,6 @@ | |||
327 | 1 | charmhelpers | ||
328 | 2 | charms.reactive | ||
329 | 3 | mock | ||
330 | 4 | pytest | ||
331 | 5 | pytest-cov | ||
332 | 6 | requests | ||
333 | diff --git a/unit_tests/graylog.py b/unit_tests/test_graylog.py | |||
334 | 0 | similarity index 75% | 7 | similarity index 75% |
335 | 1 | rename from unit_tests/graylog.py | 8 | rename from unit_tests/graylog.py |
336 | 2 | rename to unit_tests/test_graylog.py | 9 | rename to unit_tests/test_graylog.py |
337 | index 3394201..79cdaf0 100644 | |||
338 | --- a/unit_tests/graylog.py | |||
339 | +++ b/unit_tests/test_graylog.py | |||
340 | @@ -8,9 +8,10 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) | |||
341 | 8 | 8 | ||
342 | 9 | from reactive.graylog import ( | 9 | from reactive.graylog import ( |
343 | 10 | set_conf, | 10 | set_conf, |
347 | 11 | _check_input_exists) | 11 | set_jvm_heap_size, |
348 | 12 | from lib.graylogapi import GraylogAPI | 12 | _check_input_exists) # NOQA: E402 |
349 | 13 | from files import check_graylog_health | 13 | from lib.graylogapi import GraylogAPI # NOQA: E402 |
350 | 14 | from files import check_graylog_health # NOQA: E402 | ||
351 | 14 | 15 | ||
352 | 15 | initial_conf = u"""#key1 = value1 | 16 | initial_conf = u"""#key1 = value1 |
353 | 16 | key2 = value2 | 17 | key2 = value2 |
354 | @@ -173,3 +174,93 @@ class TestHealthCheck(unittest.TestCase): | |||
355 | 173 | 'uncommitted_journal_entries': ucommitted} | 174 | 'uncommitted_journal_entries': ucommitted} |
356 | 174 | state, _ = check_graylog_health.journal_state(mock_api, args) | 175 | state, _ = check_graylog_health.journal_state(mock_api, args) |
357 | 175 | self.assertEqual(state, exp_state) | 176 | self.assertEqual(state, exp_state) |
358 | 177 | |||
359 | 178 | |||
360 | 179 | etc_default_conf = u""" | ||
361 | 180 | # Path to the java executable. | ||
362 | 181 | JAVA=/usr/bin/java | ||
363 | 182 | |||
364 | 183 | # Default Java options for heap and garbage collection. | ||
365 | 184 | {} | ||
366 | 185 | |||
367 | 186 | # Pass some extra args to graylog-server. (i.e. "-d" to enable debug mode) | ||
368 | 187 | GRAYLOG_SERVER_ARGS="" | ||
369 | 188 | |||
370 | 189 | # Program that will be used to wrap the graylog-server command. Useful to | ||
371 | 190 | # support programs like authbind. | ||
372 | 191 | GRAYLOG_COMMAND_WRAPPER="" | ||
373 | 192 | """ | ||
374 | 193 | |||
375 | 194 | heap_default = u""" | ||
376 | 195 | GRAYLOG_SERVER_JAVA_OPTS="-Xms1g -Xmx1g -XX:NewRatio=1 -server -XX:+ResizeTLAB -XX:+UseConcMarkSweepGC \ | ||
377 | 196 | -XX:+CMSConcurrentMTEnabled -XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC -XX:-OmitStackTraceInFastThrow" | ||
378 | 197 | """ | ||
379 | 198 | |||
380 | 199 | heap_2g = u""" | ||
381 | 200 | GRAYLOG_SERVER_JAVA_OPTS="-Xms2g -Xmx2g -XX:NewRatio=1 -server -XX:+ResizeTLAB -XX:+UseConcMarkSweepGC \ | ||
382 | 201 | -XX:+CMSConcurrentMTEnabled -XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC -XX:-OmitStackTraceInFastThrow" | ||
383 | 202 | """ | ||
384 | 203 | |||
385 | 204 | heap_not_present = u""" | ||
386 | 205 | GRAYLOG_SERVER_JAVA_OPTS="-XX:NewRatio=1 -server -XX:+ResizeTLAB -XX:+UseConcMarkSweepGC -XX:+CMSConcurrentMTEnabled \ | ||
387 | 206 | -XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC -XX:-OmitStackTraceInFastThrow -Xms4g -Xmx4g" | ||
388 | 207 | """ | ||
389 | 208 | |||
390 | 209 | heap_unset = u""" | ||
391 | 210 | GRAYLOG_SERVER_JAVA_OPTS="-XX:NewRatio=1 -server -XX:+ResizeTLAB -XX:+UseConcMarkSweepGC -XX:+CMSConcurrentMTEnabled \ | ||
392 | 211 | -XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC -XX:-OmitStackTraceInFastThrow" | ||
393 | 212 | """ | ||
394 | 213 | |||
395 | 214 | heap_not_present = u""" | ||
396 | 215 | GRAYLOG_SERVER_JAVA_OPTS="-XX:NewRatio=1 -server -XX:+ResizeTLAB -XX:+UseConcMarkSweepGC -XX:+CMSConcurrentMTEnabled \ | ||
397 | 216 | -XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC -XX:-OmitStackTraceInFastThrow -Xms4g -Xmx4g" | ||
398 | 217 | """ | ||
399 | 218 | |||
400 | 219 | heap_twice = u""" | ||
401 | 220 | GRAYLOG_SERVER_JAVA_OPTS="-XX:NewRatio=1 -server -XX:+ResizeTLAB -XX:+UseConcMarkSweepGC -XX:+CMSConcurrentMTEnabled \ | ||
402 | 221 | -XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC -XX:-OmitStackTraceInFastThrow -Xms8g -Xmx8g" | ||
403 | 222 | """ | ||
404 | 223 | |||
405 | 224 | |||
406 | 225 | class TestSetJVMHeapSize(unittest.TestCase): | ||
407 | 226 | |||
408 | 227 | def setUp(self): | ||
409 | 228 | temp_file = tempfile.NamedTemporaryFile(delete=False) | ||
410 | 229 | temp_file.write(etc_default_conf.format(heap_default).encode()) | ||
411 | 230 | temp_file.close() | ||
412 | 231 | self.conf_file = temp_file.name | ||
413 | 232 | |||
414 | 233 | def tearDown(self): | ||
415 | 234 | os.remove(self.conf_file) | ||
416 | 235 | |||
417 | 236 | def conf_equals(self, want): | ||
418 | 237 | with open(self.conf_file, 'r') as conf: | ||
419 | 238 | got = conf.read() | ||
420 | 239 | if got == want: | ||
421 | 240 | return True | ||
422 | 241 | print('{}\n--- != ---\n{}'.format(got, want)) | ||
423 | 242 | return False | ||
424 | 243 | |||
425 | 244 | def test_same(self): | ||
426 | 245 | set_jvm_heap_size('1g', self.conf_file) | ||
427 | 246 | self.assertTrue(self.conf_equals(etc_default_conf.format(heap_default))) | ||
428 | 247 | |||
429 | 248 | def test_update(self): | ||
430 | 249 | set_jvm_heap_size('2g', self.conf_file) | ||
431 | 250 | self.assertTrue(self.conf_equals(etc_default_conf.format(heap_2g))) | ||
432 | 251 | |||
433 | 252 | def test_unset(self): | ||
434 | 253 | # Remove Xms and Xmx | ||
435 | 254 | set_jvm_heap_size('', self.conf_file) | ||
436 | 255 | self.assertTrue(self.conf_equals(etc_default_conf.format(heap_unset))) | ||
437 | 256 | |||
438 | 257 | def test_add(self): | ||
439 | 258 | set_jvm_heap_size('', self.conf_file) | ||
440 | 259 | set_jvm_heap_size('4g', self.conf_file) | ||
441 | 260 | self.assertTrue(self.conf_equals(etc_default_conf.format(heap_not_present))) | ||
442 | 261 | |||
443 | 262 | def test_add_twice(self): | ||
444 | 263 | set_jvm_heap_size('', self.conf_file) | ||
445 | 264 | set_jvm_heap_size('6g', self.conf_file) | ||
446 | 265 | set_jvm_heap_size('8g', self.conf_file) | ||
447 | 266 | self.assertTrue(self.conf_equals(etc_default_conf.format(heap_twice))) | ||
448 | diff --git a/unit_tests/test_logextract.py b/unit_tests/test_logextract.py | |||
449 | index fd04bf1..69d87d8 100644 | |||
450 | --- a/unit_tests/test_logextract.py | |||
451 | +++ b/unit_tests/test_logextract.py | |||
452 | @@ -2,20 +2,19 @@ import unittest | |||
453 | 2 | from unittest import mock | 2 | from unittest import mock |
454 | 3 | 3 | ||
455 | 4 | from lib import logextract | 4 | from lib import logextract |
456 | 5 | from lib.graylogapi import GraylogAPI | ||
457 | 6 | 5 | ||
458 | 7 | 6 | ||
459 | 8 | testdata_simple_pipeline_source = '\npipeline "testpipe"\nstage 1 match either\n rule "test-rule";\nend\n' | 7 | testdata_simple_pipeline_source = '\npipeline "testpipe"\nstage 1 match either\n rule "test-rule";\nend\n' |
460 | 9 | 8 | ||
461 | 10 | testdata_simple_pipeline = [{'description': None, 'stages': | 9 | testdata_simple_pipeline = [{'description': None, 'stages': |
470 | 11 | [{'match_all': False, 'rules': | 10 | [{'match_all': False, 'rules': |
471 | 12 | ['test-rule'], 'stage': 1}], | 11 | ['test-rule'], 'stage': 1}], |
472 | 13 | 'source': testdata_simple_pipeline_source, | 12 | 'source': testdata_simple_pipeline_source, |
473 | 14 | 'created_at': '2018-06-18T14:49:27.427Z', | 13 | 'created_at': '2018-06-18T14:49:27.427Z', |
474 | 15 | 'modified_at': '2018-06-18T14:49:27.427Z', | 14 | 'modified_at': '2018-06-18T14:49:27.427Z', |
475 | 16 | 'id': '5b27c6778ac7b4647301a562', | 15 | 'id': '5b27c6778ac7b4647301a562', |
476 | 17 | 'errors': None, | 16 | 'errors': None, |
477 | 18 | 'title': 'juju-logextract-pipeline'}] | 17 | 'title': 'juju-logextract-pipeline'}] |
478 | 19 | 18 | ||
479 | 20 | testdata_streams = {'total': 1, | 19 | testdata_streams = {'total': 1, |
480 | 21 | 'streams': [ | 20 | 'streams': [ |
481 | @@ -30,18 +29,19 @@ testdata_rules = [ | |||
482 | 30 | { | 29 | { |
483 | 31 | "title": "from ceph mon", | 30 | "title": "from ceph mon", |
484 | 32 | "description": "", | 31 | "description": "", |
486 | 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 |
487 | 34 | "created_at": "2018-06-17T14:32:13.632Z", | 33 | "created_at": "2018-06-17T14:32:13.632Z", |
488 | 35 | "modified_at": "2018-06-17T14:42:25.818Z", | 34 | "modified_at": "2018-06-17T14:42:25.818Z", |
489 | 36 | "errors": None, | 35 | "errors": None, |
490 | 37 | "id": "5b2670ed6140b943aef99ae9" | 36 | "id": "5b2670ed6140b943aef99ae9" |
492 | 38 | },] | 37 | }] |
493 | 39 | 38 | ||
494 | 40 | testdata_stream_connect = { | 39 | testdata_stream_connect = { |
495 | 41 | "stream_id": "000000000000000000000001", | 40 | "stream_id": "000000000000000000000001", |
497 | 42 | "pipeline_ids" : ["5b35061c6140b943ae096769"] | 41 | "pipeline_ids": ["5b35061c6140b943ae096769"] |
498 | 43 | } | 42 | } |
499 | 44 | 43 | ||
500 | 44 | |||
501 | 45 | class TestGraylogPipelines(unittest.TestCase): | 45 | class TestGraylogPipelines(unittest.TestCase): |
502 | 46 | 46 | ||
503 | 47 | @mock.patch('lib.graylogapi.GraylogAPI') | 47 | @mock.patch('lib.graylogapi.GraylogAPI') |
504 | @@ -69,7 +69,6 @@ class TestGraylogRules(unittest.TestCase): | |||
505 | 69 | self.assertEqual(rules[0]['title'], "from ceph mon") | 69 | self.assertEqual(rules[0]['title'], "from ceph mon") |
506 | 70 | 70 | ||
507 | 71 | 71 | ||
508 | 72 | |||
509 | 73 | class TestGraylogStreams(unittest.TestCase): | 72 | class TestGraylogStreams(unittest.TestCase): |
510 | 74 | 73 | ||
511 | 75 | @mock.patch('lib.graylogapi.GraylogAPI') | 74 | @mock.patch('lib.graylogapi.GraylogAPI') |
512 | @@ -77,18 +76,16 @@ class TestGraylogStreams(unittest.TestCase): | |||
513 | 77 | mock_api.request.return_value = testdata_streams | 76 | mock_api.request.return_value = testdata_streams |
514 | 78 | gstreams = logextract.GraylogStreams(mock_api) | 77 | gstreams = logextract.GraylogStreams(mock_api) |
515 | 79 | allmsgs = gstreams.get_stream_id_for("All messages") | 78 | allmsgs = gstreams.get_stream_id_for("All messages") |
518 | 80 | self.assertEqual(allmsgs, | 79 | self.assertEqual(allmsgs, testdata_streams['streams'][0]['id']) |
517 | 81 | testdata_streams['streams'][0]['id']) | ||
519 | 82 | nope = gstreams.get_stream_id_for("I don't exist") | 80 | nope = gstreams.get_stream_id_for("I don't exist") |
520 | 83 | self.assertIsNone(nope) | 81 | self.assertIsNone(nope) |
521 | 84 | 82 | ||
522 | 83 | |||
523 | 85 | class TestLogExtractPipeline(unittest.TestCase): | 84 | class TestLogExtractPipeline(unittest.TestCase): |
524 | 86 | 85 | ||
525 | 87 | @mock.patch('lib.graylogapi.GraylogAPI') | 86 | @mock.patch('lib.graylogapi.GraylogAPI') |
526 | 88 | def test_get_rules(self, mock_api): | 87 | def test_get_rules(self, mock_api): |
527 | 89 | mock_api.request.return_value = testdata_simple_pipeline | 88 | mock_api.request.return_value = testdata_simple_pipeline |
528 | 90 | logext = logextract.LogExtractPipeline(mock_api) | ||
529 | 91 | rules = logext.get_rules() | ||
530 | 92 | 89 | ||
531 | 93 | def test_parse_rule_title(self): | 90 | def test_parse_rule_title(self): |
532 | 94 | logext = logextract.LogExtractPipeline() | 91 | logext = logextract.LogExtractPipeline() |
This merge proposal is being monitored by mergebot. Change the status to Approved to merge.