Merge ~vultaire/charm-graylog:adding-zaza-tests into ~graylog-charmers/charm-graylog:master

Proposed by Paul Goins
Status: Merged
Approved by: Xav Paice
Approved revision: 8168d755429d15d38e832c112440d6f42896636f
Merged at revision: 9e01c58565939a645ab53d617cddaebbdbcca467
Proposed branch: ~vultaire/charm-graylog:adding-zaza-tests
Merge into: ~graylog-charmers/charm-graylog:master
Diff against target: 317 lines (+206/-10)
7 files modified
lib/charms/layer/graylog/logextract.py (+12/-4)
tests/README.md (+12/-0)
tests/bundles/bionic-graylog2.yaml (+9/-2)
tests/bundles/bionic-graylog3.yaml (+45/-0)
tests/bundles/bionic-ha.yaml (+8/-0)
tests/test_legacy.py (+110/-0)
tests/tests.yaml (+10/-4)
Reviewer Review Type Date Requested Status
Xav Paice (community) Approve
Alvaro Uria (community) Approve
Canonical IS Reviewers Pending
Review via email: mp+378537@code.launchpad.net

Commit message

Adding initial zaza tests via "tox -e func"

This patch provides zaza-compatible ports of the charm's original
amulet-based test suite along with the relevant modifications
necessary to enable them to be run. This is intended to provide a
base for future development which includes functional testing.

Description of the change

* lib/charms/layer/graylog/logextract.py: Converted class-level 'url' variables into properties; is_v2() calls juju helpers and thus is not suitable to be called at import-time. If left as-is, tests cannot run because of the missing juju helper binaries.

* tests/README.md: Provided simple instructions about how to build the charm and run the functional tests. Includes important notes about running behind a proxy.

* tests/bundles/**: Temporarily removed the bionic-ha bundle (since we don't yet have HA support), and replaced the bionic bundle with different versions for Graylog 2 and 3. Other small changes were done, including (but not limited to) changes to better allow tests to run via Zaza.

* tests/test_legacy.py: This is a suite of tests based upon the original Amulet-driven tests included with this charm in the past, but ported to work with Zaza. The majority of the original test coverage should be provided by these new tests.

* tests/tests.yaml: This file appears to have been more-or-less a placeholder. Now it provides a real test and has been updated to allow clean deploy and settlement of the bundles.

* tox.ini: A build command has been added, and minimal changes have been made to the func target to allow it to run zaza tests correctly.

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
Alvaro Uria (aluria) wrote :

Overall, everything looks good, thank you. I added minor comments (ie. make tests support future HA), and a strong suggestion to use Makefile (and document it in tests/README) to build the charm and run func tests. The Makefile is already there, so the MP probably needs a minor tweak and the tests/README to be updated.

review: Needs Fixing
Revision history for this message
Paul Goins (vultaire) wrote :

Understood. I will make the updates regarding get_graylog_client() and the Makefile. I will also update this to go more in line with the path Peter has taken in his MR regarding building charms (https://code.launchpad.net/~peter-sabaini/graylog-charm/+git/graylog-charm/+merge/377651).

Revision history for this message
Paul Goins (vultaire) wrote :

OK; I've re-worked my code upon the new code in trunk. This is ready for review once more.

Revision history for this message
Alvaro Uria (aluria) wrote :

MP looks great, thank you. I haven't run "make test" but skimmed the changes below.

review: Approve
Revision history for this message
Xav Paice (xavpaice) wrote :

Can we please rebase this against master? Currently won't merge.

review: Needs Fixing
Revision history for this message
Xav Paice (xavpaice) wrote :

Although the actual tests are still failing for me, I'm aware there's other changes queued up that fix this and this change makes a lot of progress towards good testing. Manual testing the charm as is works fine, including looking at the resulting zaza model. Approving.

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

Change successfully merged at revision 9e01c58565939a645ab53d617cddaebbdbcca467

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/charms/layer/graylog/logextract.py b/lib/charms/layer/graylog/logextract.py
2index 5d1ae27..42c034b 100644
3--- a/lib/charms/layer/graylog/logextract.py
4+++ b/lib/charms/layer/graylog/logextract.py
5@@ -48,13 +48,21 @@ class GraylogTitleSourceItems:
6
7
8 class GraylogPipelines(GraylogTitleSourceItems):
9- url = '{}/system/pipelines/pipeline'.format(
10- '/plugins/org.graylog.plugins.pipelineprocessor' if is_v2() else '')
11+ @property
12+ def url(self):
13+ if is_v2():
14+ return '/plugins/org.graylog.plugins.pipelineprocessor/system/pipelines/pipeline'
15+ else:
16+ return '/system/pipelines/pipeline'
17
18
19 class GraylogRules(GraylogTitleSourceItems):
20- url = '{}/system/pipelines/rule'.format(
21- '/plugins/org.graylog.plugins.pipelineprocessor' if is_v2() else '')
22+ @property
23+ def url(self):
24+ if is_v2():
25+ return '/plugins/org.graylog.plugins.pipelineprocessor/system/pipelines/rule'
26+ else:
27+ return '/system/pipelines/rule'
28
29
30 class GraylogStreams:
31diff --git a/tests/README.md b/tests/README.md
32new file mode 100644
33index 0000000..50a965f
34--- /dev/null
35+++ b/tests/README.md
36@@ -0,0 +1,12 @@
37+# How to run functional tests
38+
39+1. export JUJU_REPOSITORY=<directory for built charms>
40+2. Optional: export MODEL_SETTINGS=<semicolon-separated list of "juju model-config" settings>
41+3. From the repository root, run: make test
42+
43+NOTE: If you are behind a proxy, be sure to export a MODEL_SETTINGS variable as
44+described above. Note that you will need to use the http-proxy, https-proxy and
45+similar settings rather than the app-specific settings as the elasticsearch
46+charm (at the time of writing) requires the environment setting for running
47+Ansible apt-key actions, but the charm doesn't presently provide a way of
48+setting this.
49diff --git a/tests/bundles/bionic.yaml b/tests/bundles/bionic-graylog2.yaml
50similarity index 91%
51rename from tests/bundles/bionic.yaml
52rename to tests/bundles/bionic-graylog2.yaml
53index b646c7a..bd256db 100644
54--- a/tests/bundles/bionic.yaml
55+++ b/tests/bundles/bionic-graylog2.yaml
56@@ -12,11 +12,13 @@ applications:
57 graylog:
58 num_units: 1
59 series: bionic
60-
61+ options:
62+ channel: 2/stable
63+
64 elastic:
65 charm: cs:elasticsearch
66 num_units: 1
67-
68+
69 mongo:
70 charm: cs:mongodb
71 num_units: 1
72@@ -25,6 +27,9 @@ applications:
73 charm: cs:haproxy
74 num_units: 1
75
76+ nrpe:
77+ charm: cs:nrpe
78+
79 relations:
80 - - ubuntu
81 - filebeat
82@@ -36,3 +41,5 @@ relations:
83 - elastic
84 - - graylog
85 - haproxy
86+ - - graylog
87+ - nrpe
88diff --git a/tests/bundles/bionic-graylog3.yaml b/tests/bundles/bionic-graylog3.yaml
89new file mode 100644
90index 0000000..596cf7d
91--- /dev/null
92+++ b/tests/bundles/bionic-graylog3.yaml
93@@ -0,0 +1,45 @@
94+series: bionic
95+
96+applications:
97+ ubuntu:
98+ charm: cs:ubuntu
99+ num_units: 1
100+
101+ filebeat:
102+ charm: cs:filebeat
103+ num_units: 0
104+
105+ graylog:
106+ num_units: 1
107+ series: bionic
108+ options:
109+ channel: 3/stable
110+
111+ elastic:
112+ charm: cs:elasticsearch
113+ num_units: 1
114+
115+ mongo:
116+ charm: cs:mongodb
117+ num_units: 1
118+
119+ haproxy:
120+ charm: cs:haproxy
121+ num_units: 1
122+
123+ nrpe:
124+ charm: cs:nrpe
125+
126+relations:
127+ - - ubuntu
128+ - filebeat
129+ - - graylog:beats
130+ - filebeat:logstash
131+ - - graylog
132+ - mongo
133+ - - graylog
134+ - elastic
135+ - - graylog
136+ - haproxy
137+ - - graylog
138+ - nrpe
139diff --git a/tests/bundles/bionic-ha.yaml b/tests/bundles/bionic-ha.yaml
140index 516cff6..70cc1e9 100644
141--- a/tests/bundles/bionic-ha.yaml
142+++ b/tests/bundles/bionic-ha.yaml
143@@ -1,3 +1,4 @@
144+# NOTE: Not in use yet.
145 series: bionic
146
147 applications:
148@@ -12,6 +13,8 @@ applications:
149 graylog:
150 num_units: 3
151 series: bionic
152+ options:
153+ channel: 3/stable
154
155 elastic:
156 charm: cs:elasticsearch
157@@ -25,6 +28,9 @@ applications:
158 charm: cs:haproxy
159 num_units: 1
160
161+ nrpe:
162+ charm: cs:nrpe
163+
164 relations:
165 - - ubuntu
166 - filebeat
167@@ -36,3 +42,5 @@ relations:
168 - elastic
169 - - graylog
170 - haproxy
171+ - - graylog
172+ - nrpe
173diff --git a/tests/test_legacy.py b/tests/test_legacy.py
174new file mode 100644
175index 0000000..a92d927
176--- /dev/null
177+++ b/tests/test_legacy.py
178@@ -0,0 +1,110 @@
179+import re
180+import unittest
181+import yaml
182+from zaza.utilities import juju
183+from zaza import model
184+
185+from api import GraylogApi
186+
187+
188+DEFAULT_API_PORT = "9001" # Graylog 2 only
189+DEFAULT_WEB_PORT = "9000"
190+
191+
192+class LegacyTests(unittest.TestCase):
193+
194+ # These tests were ported from tests/test_10_basic.py in changeset a3b54c2.
195+ # They were temporarily deleted during the conversion from Amulet to Zaza.
196+ # Aside from porting to work with libjuju and some refactoring, these tests
197+ # are largely as they were before.
198+
199+ def test_api_ready(self):
200+ """Curl the api endpoint on the graylog unit."""
201+ port = self.get_api_port()
202+ curl_command = "curl http://localhost:{} --connect-timeout 30".format(port)
203+ self.run_command("graylog/0", curl_command)
204+
205+ def test_elasticsearch_active(self):
206+ self._assert_remote_address_in_server_conf("elastic/0", "client")
207+ # This was also stuck in the same test...
208+ api = self.get_graylog_clients()[0]
209+ resp = api.indexer_cluster_health()
210+ self.assertTrue(resp["status"] == "green")
211+
212+ def test_mongodb_active(self):
213+ self._assert_remote_address_in_server_conf("mongo/0", "database")
214+ # This was also stuck in the same test...
215+ api = self.get_graylog_clients()[0]
216+ resp = api.cluster_get()
217+ self.assertTrue(resp[list(resp)[0]]["is_processing"])
218+
219+ def _assert_remote_address_in_server_conf(self, remote_unit, remote_relation_name):
220+ # This is a very simplistic, naive check, but it's equivalent to
221+ # that from tests/test_10_basic.py in a3b54c2.
222+ source_unit = "graylog/0"
223+ remote_addr = juju.get_relation_from_unit(
224+ source_unit, remote_unit, remote_relation_name
225+ )["private-address"]
226+ assert remote_addr in self.get_file_contents(
227+ source_unit, "/var/snap/graylog/common/server.conf"
228+ )
229+
230+ def get_graylog_clients(self):
231+ graylog_units = juju.get_full_juju_status().applications["graylog"]["units"]
232+ graylog_addrs = [unit["public-address"] for unit in graylog_units.values()]
233+ port = self.get_api_port()
234+ password = self.get_graylog_admin_password()
235+ return [
236+ GraylogApi("http://{}:{}/api".format(graylog_addr, port), "admin", password)
237+ for graylog_addr in graylog_addrs
238+ ]
239+
240+ def get_api_port(self):
241+ port = DEFAULT_API_PORT if self.is_v2() else DEFAULT_WEB_PORT
242+ return port
243+
244+ def get_graylog_admin_password(self):
245+ result = model.run_action("graylog/0", "show-admin-password")
246+ password = result.data["results"]["admin-password"]
247+ return password
248+
249+ def test_website_active(self):
250+ data = juju.get_relation_from_unit("haproxy/0", "graylog/0", "website")
251+ self.assertEqual(data["port"], DEFAULT_WEB_PORT)
252+
253+ service_ports = {}
254+ for service in yaml.safe_load(data["all_services"]):
255+ service_ports[service["service_name"]] = service["service_port"]
256+
257+ self.assertEqual(str(service_ports["web"]), DEFAULT_WEB_PORT)
258+ if self.is_v2():
259+ self.assertEqual(str(service_ports["api"]), DEFAULT_API_PORT)
260+
261+ def run_command(self, target, command, timeout=30):
262+ result = model.run_on_unit(target, command, timeout=timeout)
263+ assert result["Code"] == "0"
264+ return result
265+
266+ def is_v2(self):
267+ return (
268+ juju.get_full_juju_status()
269+ .applications["graylog"]["workload-version"]
270+ .startswith("2.")
271+ )
272+
273+ def test_nrpe_config(self):
274+ cfg = self.get_file_contents(
275+ "nrpe/0", "/etc/nagios/nrpe.d/check_graylog_health.cfg"
276+ )
277+ self.assertTrue(re.search(r"command.*check_graylog_health", cfg))
278+
279+ def test_nrpe_health_check(self):
280+ cfg = self.get_file_contents(
281+ "nrpe/0", "/usr/local/lib/nagios/plugins/check_graylog_health.py"
282+ )
283+ self.assertTrue(re.search(r"CRITICAL", cfg))
284+
285+ def get_file_contents(self, unit, filename):
286+ result = self.run_command(unit, "cat '{}'".format(filename))
287+ assert result["Code"] == "0"
288+ return result["Stdout"]
289diff --git a/tests/tests.yaml b/tests/tests.yaml
290index 3a0510d..658fc3e 100644
291--- a/tests/tests.yaml
292+++ b/tests/tests.yaml
293@@ -1,14 +1,20 @@
294 charm_name: graylog
295 gate_bundles:
296- - bionic
297- - bionic-ha
298+ - bionic-graylog2
299+ - bionic-graylog3
300+ #- bionic-ha # Currently bionic-ha is identical to bionic-graylog3; enable
301+ # once we make changes.
302 smoke_bundles:
303- - bionic
304+ - bionic-graylog3
305 dev_bundles:
306- - bionic
307+ - bionic-graylog3
308 tests:
309+ - tests.test_legacy.LegacyTests
310 - tests.test_graylog_charm.CharmOperationTest
311 target_deploy_status:
312 filebeat:
313 workload-status: active
314 workload-status-message: 'Filebeat ready.'
315+ haproxy:
316+ workload-status: unknown
317+ workload-status-message: ""

Subscribers

People subscribed via source and target branches

to all changes: