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

Commit

Permalink
Skip non-listable API groups (#42)
Browse files Browse the repository at this point in the history
Listing resources inside API groups may fail, especially if they're
aggregated and the downstream service is faulty. Handle and log
exceptions during resource collection instead of failing the whole
clean-up loop.
  • Loading branch information
twz123 authored and hjacobs committed Sep 4, 2019
1 parent a2b65e7 commit 0899a31
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 7 deletions.
17 changes: 10 additions & 7 deletions kube_janitor/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@ def discover_namespaced_api_resources(api):
r = api.get(version='/apis')
r.raise_for_status()
for group in r.json()['groups']:
pref_version = group['preferredVersion']['groupVersion']
logger.debug(f'Collecting resources for {pref_version}..')
r2 = api.get(version=pref_version)
r2.raise_for_status()
for resource in r2.json()['resources']:
if resource['namespaced'] and 'delete' in resource['verbs'] and '/' not in resource['name']:
yield pref_version, resource
try:
pref_version = group['preferredVersion']['groupVersion']
logger.debug(f'Collecting resources in API group {pref_version}..')
r2 = api.get(version=pref_version)
r2.raise_for_status()
for resource in r2.json()['resources']:
if resource['namespaced'] and 'delete' in resource['verbs'] and '/' not in resource['name']:
yield pref_version, resource
except Exception as e:
logger.error(f'Could not collect resources in API group {pref_version}: {e}')


def get_namespaced_resource_types(api):
Expand Down
38 changes: 38 additions & 0 deletions tests/test_clean_up.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,44 @@ def get(**kwargs):
assert counter['resources-processed'] == 1


def test_ignore_nonlistable_api_group():
api_mock = MagicMock(spec=NamespacedAPIObject, name='APIMock')

def get(**kwargs):
if kwargs.get('url') == 'namespaces':
data = {'items': [{'metadata': {'name': 'ns-1'}}]}
elif kwargs.get('url') == 'customfoos':
data = {'items': [{'metadata': {
'name': 'foo-1',
'namespace': 'ns-1',
'creationTimestamp': '2019-01-17T15:14:38Z',
# invalid TTL (no unit suffix)
'annotations': {'janitor/ttl': '123'}}}]}
elif kwargs['version'] == 'v1':
data = {'resources': []}
elif kwargs['version'] == 'srcco.de/v1':
data = {'resources': [{'kind': 'CustomFoo', 'name': 'customfoos', 'namespaced': True, 'verbs': ['delete']}]}
elif kwargs['version'] == 'kaput.srcco.de/v1':
raise Exception('Catch me if you can!')
elif kwargs['version'] == '/apis':
data = {'groups': [
{'preferredVersion': {'groupVersion': 'kaput.srcco.de/v1'}},
{'preferredVersion': {'groupVersion': 'srcco.de/v1'}},
]}
else:
data = {}
response = MagicMock()
response.json.return_value = data
return response

api_mock.get = get
counter = clean_up(api_mock, ALL, [], ALL, [], [], None, dry_run=False)
assert counter['resources-processed'] == 2
assert counter['customfoos-with-ttl'] == 0
assert counter['customfoos-deleted'] == 0
assert not api_mock.delete.called


def test_ignore_invalid_ttl():
api_mock = MagicMock(spec=NamespacedAPIObject, name='APIMock')

Expand Down

0 comments on commit 0899a31

Please sign in to comment.