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

Commit

Permalink
Merge pull request #160 from nolar/patch-of-unexistent
Browse files Browse the repository at this point in the history
Ignore "404 Not Found" when patching after deletion during handling
  • Loading branch information
Sergey Vasilyev committed Aug 8, 2019
2 parents d057ac9 + 48a6abb commit ff8af12
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 3 deletions.
21 changes: 19 additions & 2 deletions kopf/clients/patching.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import asyncio

import pykube
import requests

from kopf import config
from kopf.clients import auth
from kopf.clients import classes
Expand Down Expand Up @@ -31,5 +34,19 @@ async def patch_obj(*, resource, patch, namespace=None, name=None, body=None):
cls = classes._make_cls(resource=resource)
obj = cls(api, body)

loop = asyncio.get_running_loop()
await loop.run_in_executor(config.WorkersConfig.get_syn_executor(), obj.patch, patch)
# The handler could delete its own object, so we have nothing to patch. It is okay, ignore.
try:
loop = asyncio.get_running_loop()
await loop.run_in_executor(config.WorkersConfig.get_syn_executor(), obj.patch, patch)
except pykube.ObjectDoesNotExist:
pass
except pykube.exceptions.HTTPError as e:
if e.code == 404:
pass
else:
raise
except requests.exceptions.HTTPError as e:
if e.response.status_code == 404:
pass
else:
raise
39 changes: 39 additions & 0 deletions tests/k8s/test_patching.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import json

import pykube.exceptions
import pytest
import requests

from kopf.clients.patching import patch_obj

Expand Down Expand Up @@ -98,3 +100,40 @@ async def test_raises_when_body_conflicts_with_ids(req_mock, resource):
await patch_obj(resource=resource, body=body, namespace='ns1', name='name1', patch=patch)

assert not req_mock.patch.called


@pytest.mark.parametrize('status', [404])
async def test_ignores_absent_objects_with_requests_httperror(req_mock, resource, status):
response = requests.Response()
response.status_code = status
error = requests.exceptions.HTTPError("boo!", response=response)
req_mock.patch.side_effect = error

patch = {'x': 'y'}
body = {'metadata': {'namespace': 'ns1', 'name': 'name1'}}
await patch_obj(resource=resource, body=body, patch=patch)


@pytest.mark.parametrize('status', [404])
async def test_ignores_absent_objects_with_pykube_httperror(req_mock, resource, status):
error = pykube.exceptions.HTTPError(status, "boo!")
req_mock.patch.side_effect = error

patch = {'x': 'y'}
body = {'metadata': {'namespace': 'ns1', 'name': 'name1'}}
await patch_obj(resource=resource, body=body, patch=patch)


@pytest.mark.parametrize('namespace', [None, 'ns1'], ids=['without-namespace', 'with-namespace'])
@pytest.mark.parametrize('status', [400, 401, 403, 500, 666])
async def test_raises_api_errors(req_mock, resource, namespace, status):
response = requests.Response()
response.status_code = status
error = requests.exceptions.HTTPError("boo!", response=response)
req_mock.patch.side_effect = error

patch = {'x': 'y'}
body = {'metadata': {'namespace': 'ns1', 'name': 'name1'}}
with pytest.raises(requests.exceptions.HTTPError) as e:
await patch_obj(resource=resource, body=body, patch=patch)
assert e.value.response.status_code == status
1 change: 0 additions & 1 deletion tests/k8s/test_read_obj.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import pykube
import pytest
import requests

Expand Down

0 comments on commit ff8af12

Please sign in to comment.