Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Good practices - updating state upon retrying #1039

Closed
lkoniecz opened this issue Jul 21, 2023 · 6 comments
Closed

Good practices - updating state upon retrying #1039

lkoniecz opened this issue Jul 21, 2023 · 6 comments
Labels
question Further information is requested

Comments

@lkoniecz
Copy link

lkoniecz commented Jul 21, 2023

Keywords

retries, patching, state

Problem

https://kopf.readthedocs.io/en/stable/errors/#

kopf retries upon exception, if the exception is raised then the handler fails fast without returning, hence I can't update custom resource status

real-life example
my custom resource represence a HTTP request
I want to retry upon 5xx and timeouts using kopf build-int handlers retry logic

@kopf.on.update('httprequests', retries=3, backoff=10)
def handler(memo: kopf.Memo, spec, name, namespace, logger, **kwargs):
   r = requests.request(some_url)
   if r.status_code == 500:
       what now?

I can manually patch the resource and luckily it does not trigger on_update handler, but it does not seem like the right thing to do. For instance its not automatically logged via handler built-in logger.

@lkoniecz lkoniecz added the question Further information is requested label Jul 21, 2023
@asteven
Copy link
Contributor

asteven commented Jul 23, 2023

I'm probably missing something, but why not just do this?

@kopf.on.update('httprequests', retries=3, backoff=10)
def handler(memo: kopf.Memo, spec, name, namespace, logger, **kwargs):
    r = requests.request(some_url)
    if r.status_code == 500:
        raise kopf.TemporaryError(f"Resource at {some_url} returns {r.status_code}", delay=60)

@lkoniecz
Copy link
Author

That does not update status field.

@nolar
Copy link
Owner

nolar commented Jul 24, 2023

There is the patch kwarg. You can populate it with whatever you want during the handler execution. Kopf will add a few things of its own later after the error (or success) — and will apply it to the k8s api.

Manually patching the resource is also a right way to go, there is nothing wrong with it (except for one extremely rare edge case under high load, which will be fixed soon). The only downside is that you will have 2 patch api calls: one from you, one from kopf; and you will also have to authenticate somehow not with kopf’s login machinery.

@lkoniecz
Copy link
Author

@nolar
if I read the docs correctly https://kopf.readthedocs.io/en/stable/kwargs/#patching patch is a pass through object that I can fill with anything that will get passed to the patching logic

@kopf.on.update('httprequests', retries=3, backoff=10)
def handler(memo: kopf.Memo, spec, name, namespace, logger, **kwargs):
    r = requests.request(some_url)
    if r.status_code == 500:
       kwargs['patch'] = {
            'status': {
                'handler': {
                    'httpStatusCode': 500
                }
            }
        }
        raise kopf.TemporaryError(f"Resource at {some_url} returns {r.status_code}", delay=60)

is it the right way to do? I am asking, because following snippet does not work.

@nolar
Copy link
Owner

nolar commented Jul 24, 2023

The right way. But in your case, you override the kwarg key in the local dict, you do not modify the object itself. Try this:

def …(…, patch, **kwargs):
    patch.status.setdefault('handler', {})['httpStatusCode'] = 500

@lkoniecz
Copy link
Author

Perfect, it works.

Thanks for the guidance.

Closing/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants