elastalert2 2.30.0__tar.gz → 2.31.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {elastalert2-2.30.0/elastalert2.egg-info → elastalert2-2.31.0}/PKG-INFO +1 -1
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/__init__.py +10 -1
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/elastalert.py +3 -2
- elastalert2-2.31.0/elastalert/esql.py +76 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/kibana_discover.py +31 -1
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/test_rule.py +1 -1
- {elastalert2-2.30.0 → elastalert2-2.31.0/elastalert2.egg-info}/PKG-INFO +1 -1
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert2.egg-info/SOURCES.txt +1 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/setup.py +1 -1
- {elastalert2-2.30.0 → elastalert2-2.31.0}/LICENSE +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/README.md +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/__init__.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/alerta.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/alertmanager.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/chatwork.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/command.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/datadog.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/debug.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/dingtalk.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/discord.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/email.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/exotel.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/flashduty.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/gelf.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/gitter.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/googlechat.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/httppost.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/httppost2.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/indexer.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/iris.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/jira.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/lark.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/line.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/matrixhookshot.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/mattermost.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/opsgenie.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/pagerduty.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/pagertree.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/powerautomate.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/rocketchat.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/servicenow.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/ses.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/slack.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/smseagle.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/sns.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/sqs.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/stomp.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/telegram.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/tencentsms.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/thehive.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/twilio.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/victorops.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/webex_webhook.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/workwechat.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/yzj.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerters/zabbix.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/alerts.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/auth.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/config.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/create_index.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/enhancements.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/eql.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/es_mappings/7/elastalert.json +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/es_mappings/7/elastalert_error.json +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/es_mappings/7/elastalert_status.json +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/es_mappings/7/past_elastalert.json +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/es_mappings/7/silence.json +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/es_mappings/8/elastalert.json +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/es_mappings/8/elastalert_error.json +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/es_mappings/8/elastalert_status.json +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/es_mappings/8/past_elastalert.json +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/es_mappings/8/silence.json +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/kibana_external_url_formatter.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/loaders.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/opensearch_discover.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/opensearch_external_url_formatter.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/prometheus_wrapper.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/ruletypes.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/schema.yaml +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/util.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert/yaml.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert2.egg-info/dependency_links.txt +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert2.egg-info/entry_points.txt +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert2.egg-info/requires.txt +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/elastalert2.egg-info/top_level.txt +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/setup.cfg +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/__init__.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/alerta_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/alertmanager_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/chatwork_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/command_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/datadog_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/debug_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/dingtalk_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/discord_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/email_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/exotel_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/flashduty_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/gelf_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/gitter_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/googlechat_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/httppost2_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/httppost_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/indexer_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/iris_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/jira_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/lark_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/line_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/matrixhookshot_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/mattermost_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/opsgenie_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/pagerduty_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/pagertree_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/powerautomate_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/rocketchat_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/servicenow_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/ses_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/slack_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/smseagle_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/sns_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/sqs_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/stomp_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/telegram_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/tencentsms_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/thehive_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/twilio_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/victorops_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/webex_webhook_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/workwechat_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/yzj_test.py +0 -0
- {elastalert2-2.30.0 → elastalert2-2.31.0}/tests/alerters/zabbix_test.py +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
import copy
|
|
3
3
|
import elastalert.eql as eql
|
|
4
|
+
import elastalert.esql as esql
|
|
4
5
|
|
|
5
6
|
from elasticsearch import Elasticsearch
|
|
6
7
|
from elasticsearch import RequestsHttpConnection
|
|
@@ -134,6 +135,7 @@ class ElasticSearchClient(Elasticsearch):
|
|
|
134
135
|
|
|
135
136
|
path = _make_path(index, doc_type, "_search")
|
|
136
137
|
eql_body = eql.format_request(body)
|
|
138
|
+
esql_body = esql.format_request(body)
|
|
137
139
|
if eql_body is not None:
|
|
138
140
|
path = path.replace('/_search', '/_eql/search')
|
|
139
141
|
body = eql_body
|
|
@@ -143,6 +145,10 @@ class ElasticSearchClient(Elasticsearch):
|
|
|
143
145
|
params.pop('scroll')
|
|
144
146
|
if '_source_includes' in params:
|
|
145
147
|
params.pop('_source_includes')
|
|
148
|
+
elif esql_body is not None:
|
|
149
|
+
path = "/_query"
|
|
150
|
+
body = esql_body
|
|
151
|
+
params = {'format': 'json'}
|
|
146
152
|
|
|
147
153
|
results = self.transport.perform_request(
|
|
148
154
|
"POST",
|
|
@@ -152,6 +158,9 @@ class ElasticSearchClient(Elasticsearch):
|
|
|
152
158
|
body=body,
|
|
153
159
|
)
|
|
154
160
|
|
|
155
|
-
|
|
161
|
+
if esql_body is not None:
|
|
162
|
+
esql.format_results(results, default_index=index)
|
|
163
|
+
else:
|
|
164
|
+
eql.format_results(results)
|
|
156
165
|
|
|
157
166
|
return results
|
|
@@ -337,9 +337,10 @@ class ElastAlerter(object):
|
|
|
337
337
|
|
|
338
338
|
# Convert the timestamp to a datetime
|
|
339
339
|
ts = lookup_es_key(hit['_source'], rule['timestamp_field'])
|
|
340
|
-
if
|
|
340
|
+
if ts is None:
|
|
341
341
|
raise EAException(
|
|
342
|
-
"Error:
|
|
342
|
+
f"Error: The configured timestamp_field '{rule['timestamp_field']}' was not found in the query results. "
|
|
343
|
+
f"Available fields: {list(hit['_source'].keys())}"
|
|
343
344
|
)
|
|
344
345
|
|
|
345
346
|
set_es_key(hit['_source'], rule['timestamp_field'], rule['ts_to_dt'](ts))
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def format_request(body):
|
|
6
|
+
query = body.get('query')
|
|
7
|
+
if not query:
|
|
8
|
+
return None
|
|
9
|
+
|
|
10
|
+
query_bool = query.get('bool')
|
|
11
|
+
if not query_bool:
|
|
12
|
+
return None
|
|
13
|
+
|
|
14
|
+
filt = query_bool.get('filter')
|
|
15
|
+
if not filt:
|
|
16
|
+
return None
|
|
17
|
+
|
|
18
|
+
filter_bool = filt.get('bool')
|
|
19
|
+
if not filter_bool:
|
|
20
|
+
return None
|
|
21
|
+
|
|
22
|
+
filter_bool_must = filter_bool.get('must')
|
|
23
|
+
if not filter_bool_must:
|
|
24
|
+
return None
|
|
25
|
+
|
|
26
|
+
other_filters = []
|
|
27
|
+
esql = None
|
|
28
|
+
for f in filter_bool_must:
|
|
29
|
+
if f.get('esql'):
|
|
30
|
+
esql = f['esql']
|
|
31
|
+
else:
|
|
32
|
+
other_filters.append(f)
|
|
33
|
+
|
|
34
|
+
if esql:
|
|
35
|
+
new_body = {'filter': {'bool': {'must': other_filters}}, 'query': esql}
|
|
36
|
+
return new_body
|
|
37
|
+
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def format_results(results, default_index=None):
|
|
42
|
+
columns = results.pop('columns', None)
|
|
43
|
+
values = results.pop('values', None)
|
|
44
|
+
if columns is None or values is None:
|
|
45
|
+
return results
|
|
46
|
+
|
|
47
|
+
col_names = [col['name'] for col in columns]
|
|
48
|
+
hits = []
|
|
49
|
+
for val_row in values:
|
|
50
|
+
doc = dict(zip(col_names, val_row))
|
|
51
|
+
|
|
52
|
+
# Pull metadata fields if present
|
|
53
|
+
doc_id = doc.get('_id', None)
|
|
54
|
+
doc_index = doc.get('_index', default_index)
|
|
55
|
+
|
|
56
|
+
if not doc_id:
|
|
57
|
+
# Generate deterministic hash of the document to use as unique ID
|
|
58
|
+
doc_hash = hashlib.sha256(json.dumps(doc, sort_keys=True, default=str).encode('utf-8')).hexdigest()
|
|
59
|
+
doc_id = doc_hash
|
|
60
|
+
|
|
61
|
+
hit = {
|
|
62
|
+
'_index': doc_index,
|
|
63
|
+
'_id': doc_id,
|
|
64
|
+
'_source': doc
|
|
65
|
+
}
|
|
66
|
+
hits.append(hit)
|
|
67
|
+
|
|
68
|
+
results['hits'] = {
|
|
69
|
+
'total': {
|
|
70
|
+
'value': len(values),
|
|
71
|
+
'relation': 'eq'
|
|
72
|
+
},
|
|
73
|
+
'hits': hits
|
|
74
|
+
}
|
|
75
|
+
results['esql'] = True
|
|
76
|
+
return results
|
|
@@ -74,6 +74,36 @@ def kibana7_disover_global_state(from_time, to_time):
|
|
|
74
74
|
} )
|
|
75
75
|
|
|
76
76
|
|
|
77
|
+
def _normalize_query_value(value):
|
|
78
|
+
"""Collapse empty/single-element query_key values before filter emission.
|
|
79
|
+
|
|
80
|
+
Elasticsearch returns multi-valued fields as arrays even when they hold a
|
|
81
|
+
single item, and rules using such fields as ``query_key`` otherwise render
|
|
82
|
+
Kibana filters with ``params.query: ['']`` — a phrase filter that matches
|
|
83
|
+
no documents, producing an empty Discover view for the reviewer.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
- ``None`` when the value is absent, an empty string, or a list that
|
|
87
|
+
collapses to nothing after dropping ``None``/empty-string entries;
|
|
88
|
+
callers emit the existing ``negate exists`` filter for this case.
|
|
89
|
+
- The sole surviving element when the input is a single-item list.
|
|
90
|
+
- The original value otherwise (scalars pass through; multi-value lists
|
|
91
|
+
are returned unchanged so callers may extend to a ``phrases`` filter).
|
|
92
|
+
"""
|
|
93
|
+
if value is None:
|
|
94
|
+
return None
|
|
95
|
+
if isinstance(value, str):
|
|
96
|
+
return None if value == '' else value
|
|
97
|
+
if isinstance(value, list):
|
|
98
|
+
cleaned = [v for v in value if v not in (None, '')]
|
|
99
|
+
if not cleaned:
|
|
100
|
+
return None
|
|
101
|
+
if len(cleaned) == 1:
|
|
102
|
+
return cleaned[0]
|
|
103
|
+
return cleaned
|
|
104
|
+
return value
|
|
105
|
+
|
|
106
|
+
|
|
77
107
|
def kibana_discover_app_state(index, columns, filters, query_keys, match):
|
|
78
108
|
app_filters = []
|
|
79
109
|
|
|
@@ -105,7 +135,7 @@ def kibana_discover_app_state(index, columns, filters, query_keys, match):
|
|
|
105
135
|
} )
|
|
106
136
|
|
|
107
137
|
for query_key in query_keys:
|
|
108
|
-
query_value = lookup_es_key(match, query_key)
|
|
138
|
+
query_value = _normalize_query_value(lookup_es_key(match, query_key))
|
|
109
139
|
|
|
110
140
|
if query_value is None:
|
|
111
141
|
app_filters.append( {
|
|
@@ -8,7 +8,7 @@ from setuptools import setup
|
|
|
8
8
|
base_dir = os.path.dirname(__file__)
|
|
9
9
|
setup(
|
|
10
10
|
name='elastalert2',
|
|
11
|
-
version='2.
|
|
11
|
+
version='2.31.0',
|
|
12
12
|
description='Automated rule-based alerting for Elasticsearch',
|
|
13
13
|
long_description=open('README.md').read(),
|
|
14
14
|
long_description_content_type="text/markdown",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|