Skip to content

Commit 2ea4aa5

Browse files
committed
Merge branch '8.x' into 8.0
2 parents d5a1a8f + b375951 commit 2ea4aa5

File tree

17 files changed

+157
-62
lines changed

17 files changed

+157
-62
lines changed

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# syntax=docker/dockerfile:1
2-
ARG PYVER=3.11.7
3-
ARG ALPTAG=3.18
2+
ARG PYVER=3.11.9
3+
ARG ALPTAG=3.19
44
FROM python:${PYVER}-alpine${ALPTAG} as builder
55

66
# Add the community repo for access to patchelf binary package

curator/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
"""Curator Version"""
2-
__version__ = '8.0.14'
2+
__version__ = '8.0.15'

curator/actions/alias.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def remove(self, ilo, warn_if_no_indices=False):
9898

9999
# Re-raise the exceptions.NoIndices so it will behave as before
100100
raise NoIndices('No indices to remove from alias') from exc
101-
aliases = self.client.indices.get_alias()
101+
aliases = self.client.indices.get_alias(expand_wildcards=['open', 'closed'])
102102
for index in ilo.working_list():
103103
if index in aliases:
104104
self.loggit.debug('Index %s in get_aliases output', index)

curator/helpers/date_ops.py

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import re
55
import string
66
import time
7-
from datetime import timedelta, datetime
7+
from datetime import timedelta, datetime, timezone
88
from elasticsearch8.exceptions import NotFoundError
99
from curator.exceptions import ConfigurationError
1010
from curator.defaults.settings import date_regex
@@ -43,6 +43,7 @@ def get_epoch(self, searchme):
4343
timestamp = match.group("date")
4444
return datetime_to_epoch(get_datetime(timestamp, self.timestring))
4545

46+
4647
def absolute_date_range(
4748
unit, date_from, date_to,
4849
date_from_format=None, date_to_format=None
@@ -77,7 +78,7 @@ def absolute_date_range(
7778
raise ConfigurationError('Must provide "date_from_format" and "date_to_format"')
7879
try:
7980
start_epoch = datetime_to_epoch(get_datetime(date_from, date_from_format))
80-
logger.debug('Start ISO8601 = %s', datetime.utcfromtimestamp(start_epoch).isoformat())
81+
logger.debug('Start ISO8601 = %s', epoch2iso(start_epoch))
8182
except Exception as err:
8283
raise ConfigurationError(
8384
f'Unable to parse "date_from" {date_from} and "date_from_format" {date_from_format}. '
@@ -116,7 +117,7 @@ def absolute_date_range(
116117
end_epoch = get_point_of_reference(
117118
unit, -1, epoch=datetime_to_epoch(end_date)) -1
118119

119-
logger.debug('End ISO8601 = %s', datetime.utcfromtimestamp(end_epoch).isoformat())
120+
logger.debug('End ISO8601 = %s', epoch2iso(end_epoch))
120121
return (start_epoch, end_epoch)
121122

122123
def date_range(unit, range_from, range_to, epoch=None, week_starts_on='sunday'):
@@ -152,7 +153,7 @@ def date_range(unit, range_from, range_to, epoch=None, week_starts_on='sunday'):
152153
if not epoch:
153154
epoch = time.time()
154155
epoch = fix_epoch(epoch)
155-
raw_point_of_ref = datetime.utcfromtimestamp(epoch)
156+
raw_point_of_ref = datetime.fromtimestamp(epoch, timezone.utc)
156157
logger.debug('Raw point of Reference = %s', raw_point_of_ref)
157158
# Reverse the polarity, because -1 as last week makes sense when read by
158159
# humans, but datetime timedelta math makes -1 in the future.
@@ -208,7 +209,7 @@ def date_range(unit, range_from, range_to, epoch=None, week_starts_on='sunday'):
208209
start_date = point_of_ref - start_delta
209210
# By this point, we know our start date and can convert it to epoch time
210211
start_epoch = datetime_to_epoch(start_date)
211-
logger.debug('Start ISO8601 = %s', datetime.utcfromtimestamp(start_epoch).isoformat())
212+
logger.debug('Start ISO8601 = %s', epoch2iso(start_epoch))
212213
# This is the number of units we need to consider.
213214
count = (range_to - range_from) + 1
214215
# We have to iterate to one more month, and then subtract a second to get
@@ -234,7 +235,7 @@ def date_range(unit, range_from, range_to, epoch=None, week_starts_on='sunday'):
234235
# to get hours, days, or weeks, as they don't change
235236
end_epoch = get_point_of_reference(
236237
unit, count * -1, epoch=start_epoch) -1
237-
logger.debug('End ISO8601 = %s', datetime.utcfromtimestamp(end_epoch).isoformat())
238+
logger.debug('End ISO8601 = %s', epoch2iso(end_epoch))
238239
return (start_epoch, end_epoch)
239240

240241
def datetime_to_epoch(mydate):
@@ -247,9 +248,53 @@ def datetime_to_epoch(mydate):
247248
:returns: An epoch timestamp based on ``mydate``
248249
:rtype: int
249250
"""
250-
tdelta = (mydate - datetime(1970, 1, 1))
251+
tdelta = mydate - datetime(1970, 1, 1)
251252
return tdelta.seconds + tdelta.days * 24 * 3600
252253

254+
def epoch2iso(epoch: int) -> str:
255+
"""
256+
Return an ISO8601 value for epoch
257+
258+
:param epoch: An epoch timestamp
259+
:type epoch: int
260+
261+
:returns: An ISO8601 timestamp
262+
:rtype: str
263+
"""
264+
# Because Python 3.12 now requires non-naive timezone declarations, we must change.
265+
#
266+
### Example:
267+
### epoch == 1491256800
268+
###
269+
### The old way:
270+
###datetime.utcfromtimestamp(epoch)
271+
### datetime.datetime(2017, 4, 3, 22, 0).isoformat()
272+
### Result: 2017-04-03T22:00:00
273+
###
274+
### The new way:
275+
### datetime.fromtimestamp(epoch, timezone.utc)
276+
### datetime.datetime(2017, 4, 3, 22, 0, tzinfo=datetime.timezone.utc).isoformat()
277+
### Result: 2017-04-03T22:00:00+00:00
278+
###
279+
### End Example
280+
#
281+
# Note that the +00:00 is appended now where we affirmatively declare the UTC timezone
282+
#
283+
# As a result, we will use this function to prune away the timezone if it is +00:00 and replace
284+
# it with Z, which is shorter Zulu notation for UTC (which Elasticsearch uses)
285+
#
286+
# We are MANUALLY, FORCEFULLY declaring timezone.utc, so it should ALWAYS be +00:00, but could
287+
# in theory sometime show up as a Z, so we test for that.
288+
289+
parts = datetime.fromtimestamp(epoch, timezone.utc).isoformat().split('+')
290+
if len(parts) == 1:
291+
if parts[0][-1] == 'Z':
292+
return parts[0] # Our ISO8601 already ends with a Z for Zulu/UTC time
293+
return f'{parts[0]}Z' # It doesn't end with a Z so we put one there
294+
if parts[1] == '00:00':
295+
return f'{parts[0]}Z' # It doesn't end with a Z so we put one there
296+
return f'{parts[0]}+{parts[1]}' # Fallback publishes the +TZ, whatever that was
297+
253298
def fix_epoch(epoch):
254299
"""
255300
Fix value of ``epoch`` to be the count since the epoch in seconds only, which should be 10 or
@@ -537,7 +582,7 @@ def parse_date_pattern(name):
537582
if char == '%':
538583
pass
539584
elif char in date_regex() and prev == '%':
540-
rendered += str(datetime.utcnow().strftime(f'%{char}'))
585+
rendered += str(datetime.now(timezone.utc).strftime(f'%{char}'))
541586
else:
542587
rendered += char
543588
logger.debug('Partially rendered name: %s', rendered)

curator/indexlist.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,6 @@ def filter_by_alias(self, aliases=None, exclude=False):
927927
def filter_by_count(self, count=None, reverse=True, use_age=False, pattern=None,
928928
source='creation_date', timestring=None, field=None, stats_result='min_value',
929929
exclude=True):
930-
# pylint: disable=anomalous-backslash-in-string
931930
"""
932931
Remove indices from the actionable list beyond the number ``count``, sorted
933932
reverse-alphabetically by default. If you set ``reverse=False``, it will be sorted
@@ -951,7 +950,7 @@ def filter_by_count(self, count=None, reverse=True, use_age=False, pattern=None,
951950
:param pattern: Select indices to count from a regular expression pattern. This pattern
952951
must have one and only one capture group. This can allow a single ``count`` filter
953952
instance to operate against any number of matching patterns, and keep ``count`` of each
954-
index in that group. For example, given a ``pattern`` of ``'^(.*)-\d{6}$'``, it will
953+
index in that group. For example, given a ``pattern`` of ``'^(.*)-\\d{6}$'``, it will
955954
match both ``rollover-000001`` and ``index-999990``, but not ``logstash-2017.10.12``.
956955
Following the same example, if my cluster also had ``rollover-000002`` through
957956
``rollover-000010`` and ``index-888888`` through ``index-999999``, it will process both

docker_test/.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export REMOTE_ES_SERVER="http://172.19.2.14:9201"

docker_test/scripts/create.sh

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,11 @@ echo "Please select one of these environment variables to prepend your 'pytest'
127127
echo
128128

129129
for IP in $IPLIST; do
130-
echo "REMOTE_ES_SERVER=\"http://$IP:${REMOTE_PORT}\""
131-
if [ "$AUTO_EXPORT" == "y" ]; then
132-
# This puts our curatortestenv file where it can be purged easily by destroy.sh
133-
cd $SCRIPTPATH
134-
cd ..
135-
echo "export REMOTE_ES_SERVER=http://$IP:$REMOTE_PORT" > curatortestenv
136-
fi
130+
REMOTE="REMOTE_ES_SERVER=\"http://$IP:${REMOTE_PORT}\""
131+
echo ${REMOTE}
132+
cd $SCRIPTPATH
133+
cd ..
134+
echo "export ${REMOTE}" > .env
137135
done
138136

139137
echo

docker_test/scripts/destroy.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ UPONE=$(pwd | awk -F\/ '{print $NF}')
2626

2727
if [[ "$UPONE" = "docker_test" ]]; then
2828
rm -rf $(pwd)/repo/*
29-
rm -rf $(pwd)/curatortestenv
29+
cp /dev/null $(pwd)/.env
3030
else
3131
echo "WARNING: Unable to automatically empty bind mounted repo path."
3232
echo "Please manually empty the contents of the repo directory!"

docs/Changelog.rst

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,36 @@
33
Changelog
44
=========
55

6+
8.0.15 (10 April 2024)
7+
----------------------
8+
9+
**Announcement**
10+
11+
* Python 3.12 support becomes official. A few changes were necessary to ``datetime`` calls
12+
which were still using naive timestamps. Tests across all minor Python versions from 3.8 - 3.12
13+
verify everything is working as expected with regards to those changes. Note that Docker builds
14+
are still running Python 3.11 as cx_Freeze still does not officially support Python 3.12.
15+
* Added infrastructure to test multiple versions of Python against the code base. This requires
16+
you to run:
17+
* ``pip install -U hatch hatchling`` -- Install prerequisites
18+
* ``hatch run docker:create X.Y.Z`` -- where ``X.Y.Z`` is an ES version on Docker Hub
19+
* ``hatch run test:pytest`` -- Run the test suite for each supported version of Python
20+
* ``hatch run docker:destroy`` -- Cleanup the Docker containers created in ``docker:create``
21+
22+
**Bugfix**
23+
24+
* A bug reported in ``es_client`` with Python versions 3.8 and 3.9 has been addressed. Going
25+
forward, testing protocol will be to ensure that Curator works with all supported versions of
26+
Python, or support will be removed (when 3.8 is EOL, for example).
27+
28+
**Changes**
29+
30+
* Address deprecation warning in ``get_alias()`` call by limiting indices to only open and
31+
closed indices via ``expand_wildcards=['open', 'closed']``.
32+
* Address test warnings for an improperly escaped ``\d`` in a docstring in ``indexlist.py``
33+
* Updated Python version in Docker build. See Dockerfile for more information.
34+
* Docker test scripts updated to make Hatch matrix testing easier (.env file)
35+
636
8.0.14 (2 April 2024)
737
---------------------
838

docs/asciidoc/index.asciidoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
:curator_version: 8.0.14
1+
:curator_version: 8.0.15
22
:curator_major: 8
33
:curator_doc_tree: 8.0
44
:es_py_version: 8.13.0
55
:es_doc_tree: 8.13
66
:stack_doc_tree: 8.13
7-
:pybuild_ver: 3.11.7
7+
:pybuild_ver: 3.11.9
88
:copyright_years: 2011-2024
99
:ref: http://www.elastic.co/guide/en/elasticsearch/reference/{es_doc_tree}
1010
:esref: http://www.elastic.co/guide/en/elasticsearch/reference/{stack_doc_tree}

0 commit comments

Comments
 (0)