Skip to content
This repository was archived by the owner on Oct 3, 2020. It is now read-only.

Commit 13505db

Browse files
antbanhjacobs
authored andcommitted
Allow to use forever as ttl for a resource. (#39)
* Allow to use `forever` as ttl for a resource. * Use proper lower() method * Fix indentation * Minimum TTL -> Maximum TTL back in documentation * Test that forever is used in the logic of resources notification.
1 parent c2324c6 commit 13505db

File tree

5 files changed

+37
-15
lines changed

5 files changed

+37
-15
lines changed

README.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ Supported Kubernetes annotations:
7171

7272
``janitor/ttl``
7373
Maximum time to live (TTL) for the annotated resource. Annotation value must be a string composed of a integer value and a unit suffix (one of ``s``, ``m``, ``h``, ``d``, or ``w``), e.g. ``120s`` (120 seconds), ``5m`` (5 minutes), ``8h`` (8 hours), ``7d`` (7 days), or ``2w`` (2 weeks).
74+
In case if resource should not be deleted by janitor - it is allowed to specify `forever`.
7475
Note that the actual time of deletion depends on the Janitor's clean up interval. The resource will be deleted if its age (delta between now and the resource creation time) is greater than the specified TTL.
7576
``janitor/expires``
7677
Absolute timestamp in the format ``YYYY-MM-DDTHH:MM:SSZ``, ``YYYY-MM-DDTHH:MM`` or ``YYYY-MM-DD`` to mark the resource for deletion after the specified date/time.

kube_janitor/helper.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@
1717
TTL_PATTERN = re.compile(r'^(\d+)([smhdw])$')
1818
DATETIME_PATTERNS = ['%Y-%m-%dT%H:%M:%SZ', '%Y-%m-%dT%H:%M', '%Y-%m-%d']
1919

20+
TTL_UNLIMITED = 'forever'
21+
2022

2123
def parse_ttl(ttl: str) -> int:
24+
if ttl.lower() == TTL_UNLIMITED:
25+
return -1
2226
match = TTL_PATTERN.match(ttl)
2327
if not match:
2428
raise ValueError(

kube_janitor/janitor.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -141,21 +141,22 @@ def handle_resource_on_ttl(resource, rules, delete_notification: int, dry_run: b
141141
except ValueError as e:
142142
logger.info(f'Ignoring invalid TTL on {resource.kind} {resource.name}: {e}')
143143
else:
144-
counter[f'{resource.endpoint}-with-ttl'] = 1
145-
age = get_age(resource)
146-
age_formatted = format_duration(int(age.total_seconds()))
147-
logger.debug(f'{resource.kind} {resource.name} with {ttl} TTL is {age_formatted} old')
148-
if age.total_seconds() > ttl_seconds:
149-
message = f'{resource.kind} {resource.name} with {ttl} TTL is {age_formatted} old and will be deleted ({reason})'
150-
logger.info(message)
151-
create_event(resource, message, "TimeToLiveExpired", dry_run=dry_run)
152-
delete(resource, dry_run=dry_run)
153-
counter[f'{resource.endpoint}-deleted'] = 1
154-
elif delete_notification:
155-
expiry_time = get_ttl_expiry_time(resource, ttl_seconds)
156-
notification_time = get_delete_notification_time(expiry_time, delete_notification)
157-
if utcnow() > notification_time and not was_notified(resource):
158-
send_delete_notification(resource, reason, expiry_time, dry_run=dry_run)
144+
if ttl_seconds > 0:
145+
counter[f'{resource.endpoint}-with-ttl'] = 1
146+
age = get_age(resource)
147+
age_formatted = format_duration(int(age.total_seconds()))
148+
logger.debug(f'{resource.kind} {resource.name} with {ttl} TTL is {age_formatted} old')
149+
if age.total_seconds() > ttl_seconds:
150+
message = f'{resource.kind} {resource.name} with {ttl} TTL is {age_formatted} old and will be deleted ({reason})'
151+
logger.info(message)
152+
create_event(resource, message, "TimeToLiveExpired", dry_run=dry_run)
153+
delete(resource, dry_run=dry_run)
154+
counter[f'{resource.endpoint}-deleted'] = 1
155+
elif delete_notification:
156+
expiry_time = get_ttl_expiry_time(resource, ttl_seconds)
157+
notification_time = get_delete_notification_time(expiry_time, delete_notification)
158+
if utcnow() > notification_time and not was_notified(resource):
159+
send_delete_notification(resource, reason, expiry_time, dry_run=dry_run)
159160

160161
return counter
161162

tests/test_delete_notification.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,20 @@ def test_handle_resource_ttl_annotation_with_notification_triggered(self, mocked
6969
handle_resource_on_ttl(resource, [], delete_notification, dry_run=True)
7070
mocked_add_notification_flag.assert_called()
7171

72+
@unittest.mock.patch('kube_janitor.janitor.utcnow', return_value=datetime.datetime.strptime('2019-03-11T11:13:09Z', '%Y-%m-%dT%H:%M:%SZ'))
73+
@unittest.mock.patch('kube_janitor.janitor.add_notification_flag')
74+
def test_handle_resource_ttl_annotation_with_forever_value_not_triggered(self, mocked_add_notification_flag, mocked_utcnow):
75+
# Resource was created: 2019-03-11T11:05:00Z
76+
# ttl is `forever`, so it will not expire
77+
# Current datetime is: 2019-03-11T11:13:09Z
78+
# Notification is 3 minutes: 180s. Has to notify after: 2019-03-11T11:12:00Z
79+
resource = Namespace(None, {'metadata': {'name': 'foo', 'annotations': {'janitor/ttl': 'forever'}, 'creationTimestamp': '2019-03-11T11:05:00Z'}})
80+
delete_notification = 180
81+
counter = handle_resource_on_ttl(resource, [], delete_notification, dry_run=True)
82+
self.assertEqual(1, counter['resources-processed'])
83+
self.assertEqual(1, len(counter))
84+
mocked_add_notification_flag.assert_not_called()
85+
7286
@unittest.mock.patch('kube_janitor.janitor.utcnow', return_value=datetime.datetime.strptime('2019-03-11T11:13:09Z', '%Y-%m-%dT%H:%M:%SZ'))
7387
@unittest.mock.patch('kube_janitor.janitor.create_event')
7488
def test_handle_resource_ttl_annotation_notification_event(self, mocked_create_event, mocked_utcnow):

tests/test_parse_ttl.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ def test_parse_ttl():
1616
assert parse_ttl('2h') == 3600*2
1717
assert parse_ttl('7d') == 3600*24*7
1818
assert parse_ttl('1w') == 3600*24*7
19+
20+
assert parse_ttl('forever') < 0

0 commit comments

Comments
 (0)