blob: 56898fe6912101ddd84a18f67d1d4990f52103bf [file] [log] [blame]
Oleksii Zhurba020fab42017-11-01 20:13:28 +00001import json
2import requests
Oleksii Zhurba84ce7fe2018-01-16 21:34:01 +00003import datetime
Oleksii Zhurba9848e212018-09-05 10:53:51 -05004import pytest
Oleksii Zhurba020fab42017-11-01 20:13:28 +00005
Hanna Arhipovac6a022a2020-02-11 22:17:20 +02006import utils
7import logging
8
9# ################################ FIXTURES ##################################
10
11
12def prometheus_rules():
13 salt = utils.init_salt_client()
14
15 IP = salt.pillar_get(param='_param:cluster_public_host')
16 proto = salt.pillar_get(
17 param='_param:cluster_public_protocol')
18 proxies = {"http": None, "https": None}
19
20 prometheus_password = (
21 # new password in 2019.2.7
22 salt.pillar_get(
23 tgt="nginx:server",
24 param='_param:nginx_proxy_prometheus_server_password')
25
26 # Generated password ~2019.2.4
27 or salt.pillar_get(
28 param='_param:prometheus_server_proxy_password_generated')
29
30 # old password ~ 2019.2.0
31 or salt.pillar_get(
32 param='_param:keepalived_prometheus_vip_password_generated')
Hanna Arhipovaa9bd1d42020-05-20 16:23:57 +030033
34 or ""
Hanna Arhipovac6a022a2020-02-11 22:17:20 +020035 )
36
Hanna Arhipovaa9bd1d42020-05-20 16:23:57 +030037 if prometheus_password == "":
38 logging.warning("Got empty prometheus_password. \
39 Possibly this cluster with no Stacklight component")
40 return dict()
41
Hanna Arhipovac6a022a2020-02-11 22:17:20 +020042 response = requests.get(
43 '{0}://{1}:15010/api/v1/rules'.format(proto, IP),
44 proxies=proxies,
45 auth=('prometheus', prometheus_password),
46 verify=False)
47
48 if not response.status_code == 200:
Hanna Arhipovaa9bd1d42020-05-20 16:23:57 +030049 logging.warning(
Valeriy Sakharov70cdb902022-04-11 14:35:10 +040050 "Got response with incorrect status: {}. Switch to the internal network".format(response))
51 IP = salt.pillar_get(param='_param:prometheus_control_address')
52 proto = salt.pillar_get(param='_param:cluster_internal_protocol')
53 response = requests.get(
54 '{0}://{1}:15010/api/v1/rules'.format(proto, IP),
55 proxies=proxies,
56 auth=('prometheus', prometheus_password),
57 verify=False)
Hanna Arhipovac6a022a2020-02-11 22:17:20 +020058
59 content = json.loads(response.content.decode())
60 rules = content['data']['groups'][0]["rules"]
61
62 # collect rules with dict {'rulename' : {<rulecontent>}}
63 alerts_by_name = {rule['name']: rule['alerts']
64 for rule in rules
65 }
66 logging.debug("collected next rules: {}".format(alerts_by_name))
67 return alerts_by_name
68
69
70prometheus_rules = prometheus_rules()
71
72
Hanna Arhipovaa9bd1d42020-05-20 16:23:57 +030073@pytest.mark.usefixtures('check_prometheus')
Hanna Arhipovac6a022a2020-02-11 22:17:20 +020074@pytest.fixture(scope='session',
75 ids=prometheus_rules.keys(),
76 params=prometheus_rules.values())
77def alert_in_prometheus(request):
78 return request.param
79
80# ############################## TESTS #######################################
81
82
Oleksii Zhurba23c18332019-05-09 18:53:40 -050083@pytest.mark.sl_dup
Hanna Arhipovac6a022a2020-02-11 22:17:20 +020084# ElasticsearchClusterHealthStatusMajor or stacklight-pytest
Oleksii Zhurba23c18332019-05-09 18:53:40 -050085@pytest.mark.full
Oleksii Zhurba8ce9fcf2018-10-05 18:38:22 +030086@pytest.mark.usefixtures('check_kibana')
Oleksii Zhurba020fab42017-11-01 20:13:28 +000087def test_elasticsearch_cluster(local_salt_client):
Hanna Arhipovae6ed8e42019-05-15 16:27:08 +030088 salt_output = local_salt_client.pillar_get(
89 tgt='kibana:server',
90 param='_param:haproxy_elasticsearch_bind_host')
Oleksii Zhurba7d4f07e2019-06-10 17:30:53 -050091 ssl = local_salt_client.pillar_get(
92 tgt='elasticsearch:server',
93 param='haproxy:proxy:listen:elasticsearch:binds:ssl:enabled')
Oleksii Zhurba612ce7c2019-06-19 14:56:34 -050094 proto = "https" if ssl else "http"
Oleksii Zhurba9848e212018-09-05 10:53:51 -050095
Oleksii Zhurbae592ed12018-06-21 18:01:09 -050096 proxies = {"http": None, "https": None}
Hanna Arhipovae6ed8e42019-05-15 16:27:08 +030097 IP = salt_output
Dmitriy Kruglovbc0a88b2019-08-20 11:45:35 +020098 response = requests.get(
99 '{0}://{1}:9200/'.format(proto, IP),
100 proxies=proxies,
101 verify=False)
102 assert response.status_code == 200, (
103 "Issues with accessing elasticsearch on {}.".format(IP))
104 response = requests.get(
105 '{0}://{1}:9200/_cat/health'.format(proto, IP),
106 proxies=proxies,
Ekaterina Chernovac73bc4e2019-11-12 14:56:03 +0300107 verify=False).content.decode()
Dmitriy Kruglovbc0a88b2019-08-20 11:45:35 +0200108 msg = "elasticsearch is not healthy:\n{}".format(
109 json.dumps(response, indent=4))
Ekaterina Chernovac73bc4e2019-11-12 14:56:03 +0300110 assert response.split()[3] == 'green', msg
Dmitriy Kruglovbc0a88b2019-08-20 11:45:35 +0200111 assert response.split()[4] == '3', msg
112 assert response.split()[5] == '3', msg
113 assert response.split()[10] == '0', msg
114 assert response.split()[13] == '100.0%', msg
Oleksii Zhurba020fab42017-11-01 20:13:28 +0000115
116
Oleksii Zhurba23c18332019-05-09 18:53:40 -0500117@pytest.mark.sl_dup
Hanna Arhipovac6a022a2020-02-11 22:17:20 +0200118# stacklight-pytest
Oleksii Zhurba23c18332019-05-09 18:53:40 -0500119@pytest.mark.full
Oleksii Zhurba8ce9fcf2018-10-05 18:38:22 +0300120@pytest.mark.usefixtures('check_kibana')
Ievgeniia Zadorozhna511f0ce2018-11-08 17:43:10 +0300121def test_kibana_status(local_salt_client):
122 proxies = {"http": None, "https": None}
Hanna Arhipovae6ed8e42019-05-15 16:27:08 +0300123 IP = local_salt_client.pillar_get(param='_param:stacklight_log_address')
Oleksii Zhurba7d4f07e2019-06-10 17:30:53 -0500124 ssl = local_salt_client.pillar_get(
125 tgt='kibana:server',
126 param='haproxy:proxy:listen:kibana:binds:ssl:enabled')
Oleksii Zhurba612ce7c2019-06-19 14:56:34 -0500127 proto = "https" if ssl else "http"
Oleksii Zhurba7d4f07e2019-06-10 17:30:53 -0500128
Dmitriy Kruglovbc0a88b2019-08-20 11:45:35 +0200129 response = requests.get(
130 '{0}://{1}:5601/api/status'.format(proto, IP),
131 proxies=proxies,
Ekaterina Chernovac73bc4e2019-11-12 14:56:03 +0300132 verify=False).content.decode()
Dmitriy Kruglovbc0a88b2019-08-20 11:45:35 +0200133 body = json.loads(response)
134 assert body['status']['overall']['state'] == "green", (
135 "Kibana overall status is not 'green':\n{}".format(
136 body['status']['overall'])
137 )
Ievgeniia Zadorozhna511f0ce2018-11-08 17:43:10 +0300138 for i in body['status']['statuses']:
Dmitriy Kruglovbc0a88b2019-08-20 11:45:35 +0200139 assert i['state'] == "green", (
140 "Kibana statuses are unexpected:\n{}".format(i))
Ievgeniia Zadorozhna511f0ce2018-11-08 17:43:10 +0300141
142
Oleksii Zhurba23c18332019-05-09 18:53:40 -0500143@pytest.mark.smoke
144#TODO: recheck
Ievgeniia Zadorozhna511f0ce2018-11-08 17:43:10 +0300145@pytest.mark.usefixtures('check_kibana')
Oleksii Zhurba84ce7fe2018-01-16 21:34:01 +0000146def test_elasticsearch_node_count(local_salt_client):
147 now = datetime.datetime.now()
148 today = now.strftime("%Y.%m.%d")
Hanna Arhipovae6ed8e42019-05-15 16:27:08 +0300149 salt_output = local_salt_client.pillar_get(
150 tgt='kibana:server',
151 param='_param:haproxy_elasticsearch_bind_host')
Oleksii Zhurba9848e212018-09-05 10:53:51 -0500152
Hanna Arhipovae6ed8e42019-05-15 16:27:08 +0300153 IP = salt_output
Oleksii Zhurba7d4f07e2019-06-10 17:30:53 -0500154 ssl = local_salt_client.pillar_get(
155 tgt='elasticsearch:server',
156 param='haproxy:proxy:listen:elasticsearch:binds:ssl:enabled')
Oleksii Zhurba612ce7c2019-06-19 14:56:34 -0500157 proto = "https" if ssl else "http"
Oleksii Zhurba7d4f07e2019-06-10 17:30:53 -0500158
Tatyana Leontoviched57cb02019-01-11 16:26:32 +0200159 headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
Oleksii Zhurbae592ed12018-06-21 18:01:09 -0500160 proxies = {"http": None, "https": None}
Tatyana Leontoviched57cb02019-01-11 16:26:32 +0200161 data = ('{"size": 0, "aggs": '
162 '{"uniq_hostname": '
Oleksii Zhurba23c18332019-05-09 18:53:40 -0500163 '{"terms": {"size": 500, '
Tatyana Leontoviched57cb02019-01-11 16:26:32 +0200164 '"field": "Hostname.keyword"}}}}')
165 response = requests.post(
Oleksii Zhurba7d4f07e2019-06-10 17:30:53 -0500166 '{0}://{1}:9200/log-{2}/_search?pretty'.format(proto, IP, today),
Tatyana Leontoviched57cb02019-01-11 16:26:32 +0200167 proxies=proxies,
168 headers=headers,
Dmitriy Kruglovbc0a88b2019-08-20 11:45:35 +0200169 verify=False,
Tatyana Leontoviched57cb02019-01-11 16:26:32 +0200170 data=data)
Dmitriy Kruglovbc0a88b2019-08-20 11:45:35 +0200171 assert response.status_code == 200, (
172 'Issues with accessing elasticsearch on {}:\n{}'.format(
173 IP, response.text)
174 )
Tatyana Leontoviched57cb02019-01-11 16:26:32 +0200175 resp = json.loads(response.text)
Hanna Arhipovac6a022a2020-02-11 22:17:20 +0200176 cluster_domain = local_salt_client.pillar_get(
177 param='_param:cluster_domain')
Oleksii Zhurbad2847dc2018-02-16 15:13:09 -0600178 monitored_nodes = []
Oleksii Zhurba7f463412018-03-21 16:32:44 -0500179 for item_ in resp['aggregations']['uniq_hostname']['buckets']:
Oleksii Zhurbad2847dc2018-02-16 15:13:09 -0600180 node_name = item_['key']
181 monitored_nodes.append(node_name + '.' + cluster_domain)
182 missing_nodes = []
Ekaterina Chernovac73bc4e2019-11-12 14:56:03 +0300183 all_nodes = list(local_salt_client.test_ping(tgt='*').keys())
Hanna Arhipovae6ed8e42019-05-15 16:27:08 +0300184 for node in all_nodes:
Oleksii Zhurbad2847dc2018-02-16 15:13:09 -0600185 if node not in monitored_nodes:
186 missing_nodes.append(node)
Dmitriy Kruglovbc0a88b2019-08-20 11:45:35 +0200187 assert len(missing_nodes) == 0, (
188 "Not all nodes are in Elasticsearch. Expected {}, but found {} keys.\n"
189 "Missing nodes:\n{}".format(
190 len(monitored_nodes), len(all_nodes), missing_nodes)
191 )
Oleksii Zhurba84ce7fe2018-01-16 21:34:01 +0000192
193
Oleksii Zhurba23c18332019-05-09 18:53:40 -0500194@pytest.mark.sl_dup
Hanna Arhipovac6a022a2020-02-11 22:17:20 +0200195# DockerServiceMonitoring*
Oleksii Zhurba23c18332019-05-09 18:53:40 -0500196@pytest.mark.full
Oleksii Zhurba020fab42017-11-01 20:13:28 +0000197def test_stacklight_services_replicas(local_salt_client):
Oleksii Zhurba8ce9fcf2018-10-05 18:38:22 +0300198 # TODO
199 # change to docker:swarm:role:master ?
Oleksii Zhurba020fab42017-11-01 20:13:28 +0000200 salt_output = local_salt_client.cmd(
Hanna Arhipovae6ed8e42019-05-15 16:27:08 +0300201 tgt='I@docker:client:stack:monitoring and I@prometheus:server',
202 param='docker service ls',
Oleksii Zhurba8ce9fcf2018-10-05 18:38:22 +0300203 expr_form='compound')
Oleksii Zhurba9848e212018-09-05 10:53:51 -0500204
205 if not salt_output:
Oleksii Zhurba8ce9fcf2018-10-05 18:38:22 +0300206 pytest.skip("docker:client:stack:monitoring or \
207 prometheus:server pillars are not found on this environment.")
Oleksii Zhurba9848e212018-09-05 10:53:51 -0500208
Oleksii Zhurba020fab42017-11-01 20:13:28 +0000209 wrong_items = []
Ekaterina Chernovac73bc4e2019-11-12 14:56:03 +0300210 for line in salt_output[list(salt_output.keys())[0]].split('\n'):
Oleksii Zhurba020fab42017-11-01 20:13:28 +0000211 if line[line.find('/') - 1] != line[line.find('/') + 1] \
212 and 'replicated' in line:
213 wrong_items.append(line)
Dmitriy Kruglovbc0a88b2019-08-20 11:45:35 +0200214 assert len(wrong_items) == 0, (
215 "Some monitoring services don't have the expected number of "
216 "replicas:\n{}".format(json.dumps(wrong_items, indent=4))
217 )
Oleksii Zhurba020fab42017-11-01 20:13:28 +0000218
219
Oleksii Zhurba23c18332019-05-09 18:53:40 -0500220@pytest.mark.smoke
Hanna Arhipovac6a022a2020-02-11 22:17:20 +0200221def test_prometheus_alert_count(alert_in_prometheus):
Hanna Arhipova3fc06572019-12-09 15:57:55 +0200222
Hanna Arhipovac6a022a2020-02-11 22:17:20 +0200223 assert len(alert_in_prometheus) == 0, \
224 '\n\n\tAlertManager page has some alerts!\n{} \n'.format(
225 '\n'.join(
226 [alert['annotations']['description']
227 for alert in alert_in_prometheus]
228 ))
Oleksii Zhurba468e6c72018-01-16 17:43:15 +0000229
230
Oleksii Zhurba23c18332019-05-09 18:53:40 -0500231@pytest.mark.sl_dup
Hanna Arhipovac6a022a2020-02-11 22:17:20 +0200232# DockerServiceMonitoring* ??
Oleksii Zhurba23c18332019-05-09 18:53:40 -0500233@pytest.mark.full
Oleksii Zhurba020fab42017-11-01 20:13:28 +0000234def test_stacklight_containers_status(local_salt_client):
235 salt_output = local_salt_client.cmd(
Hanna Arhipovae6ed8e42019-05-15 16:27:08 +0300236 tgt='I@docker:swarm:role:master and I@prometheus:server',
237 param='docker service ps $(docker stack services -q monitoring)',
Oleksii Zhurba8ce9fcf2018-10-05 18:38:22 +0300238 expr_form='compound')
Oleksii Zhurba9848e212018-09-05 10:53:51 -0500239
240 if not salt_output:
Dmitriy Kruglovbc0a88b2019-08-20 11:45:35 +0200241 pytest.skip("docker:swarm:role:master or prometheus:server pillars "
242 "are not found on this environment.")
Oleksii Zhurba9848e212018-09-05 10:53:51 -0500243
Oleksii Zhurba020fab42017-11-01 20:13:28 +0000244 result = {}
Oleksii Zhurba468e6c72018-01-16 17:43:15 +0000245 # for old reclass models, docker:swarm:role:master can return
246 # 2 nodes instead of one. Here is temporary fix.
247 # TODO
Ekaterina Chernovac73bc4e2019-11-12 14:56:03 +0300248 if len(list(salt_output.keys())) > 1:
249 if 'CURRENT STATE' not in salt_output[list(salt_output.keys())[0]]:
250 del salt_output[list(salt_output.keys())[0]]
251 for line in salt_output[list(salt_output.keys())[0]].split('\n')[1:]:
Oleksii Zhurba020fab42017-11-01 20:13:28 +0000252 shift = 0
Oleksii Zhurba020fab42017-11-01 20:13:28 +0000253 if line.split()[1] == '\\_':
254 shift = 1
Ekaterina Chernovac73bc4e2019-11-12 14:56:03 +0300255 if line.split()[1 + shift] not in list(result.keys()):
Oleksii Zhurba020fab42017-11-01 20:13:28 +0000256 result[line.split()[1]] = 'NOT OK'
257 if line.split()[4 + shift] == 'Running' \
258 or line.split()[4 + shift] == 'Ready':
259 result[line.split()[1 + shift]] = 'OK'
Ekaterina Chernovac73bc4e2019-11-12 14:56:03 +0300260 assert 'NOT OK' not in list(result.values()), (
Dmitriy Kruglovbc0a88b2019-08-20 11:45:35 +0200261 "Some containers have incorrect state:\n{}".format(
262 json.dumps(result, indent=4))
263 )
Oleksii Zhurbae592ed12018-06-21 18:01:09 -0500264
265
Oleksii Zhurba23c18332019-05-09 18:53:40 -0500266@pytest.mark.sl_dup
Hanna Arhipovac6a022a2020-02-11 22:17:20 +0200267# PrometheusTargetDown
Oleksii Zhurba23c18332019-05-09 18:53:40 -0500268@pytest.mark.full
Oleksii Zhurbae592ed12018-06-21 18:01:09 -0500269def test_running_telegraf_services(local_salt_client):
Hanna Arhipovae6ed8e42019-05-15 16:27:08 +0300270 salt_output = local_salt_client.cmd(tgt='telegraf:agent',
271 fun='service.status',
272 param='telegraf',
273 expr_form='pillar',)
Oleksii Zhurba9848e212018-09-05 10:53:51 -0500274
275 if not salt_output:
Dmitriy Kruglovbc0a88b2019-08-20 11:45:35 +0200276 pytest.skip("Telegraf or telegraf:agent pillars are not found on "
277 "this environment.")
Oleksii Zhurba9848e212018-09-05 10:53:51 -0500278
Oleksii Zhurbae592ed12018-06-21 18:01:09 -0500279 result = [{node: status} for node, status
Ekaterina Chernovac73bc4e2019-11-12 14:56:03 +0300280 in list(salt_output.items())
Oleksii Zhurbae592ed12018-06-21 18:01:09 -0500281 if status is False]
Dmitriy Kruglovbc0a88b2019-08-20 11:45:35 +0200282 assert result == [], (
283 "Telegraf service is not running on the following nodes:\n{}".format(
284 result)
285 )
Ievgeniia Zadorozhna6775eb72018-11-09 19:50:04 +0300286
287
Oleksii Zhurba23c18332019-05-09 18:53:40 -0500288@pytest.mark.sl_dup
Hanna Arhipovac6a022a2020-02-11 22:17:20 +0200289# PrometheusTargetDown
Oleksii Zhurba23c18332019-05-09 18:53:40 -0500290@pytest.mark.full
Ievgeniia Zadorozhna6775eb72018-11-09 19:50:04 +0300291def test_running_fluentd_services(local_salt_client):
Hanna Arhipovae6ed8e42019-05-15 16:27:08 +0300292 salt_output = local_salt_client.cmd(tgt='fluentd:agent',
293 fun='service.status',
294 param='td-agent',
Ievgeniia Zadorozhna6775eb72018-11-09 19:50:04 +0300295 expr_form='pillar')
296 result = [{node: status} for node, status
Ekaterina Chernovac73bc4e2019-11-12 14:56:03 +0300297 in list(salt_output.items())
Ievgeniia Zadorozhna6775eb72018-11-09 19:50:04 +0300298 if status is False]
Dmitriy Kruglovbc0a88b2019-08-20 11:45:35 +0200299 assert result == [], (
300 "Fluentd check failed - td-agent service is not running on the "
301 "following nodes:\n{}".format(result)
302 )