-
Notifications
You must be signed in to change notification settings - Fork 87
Helm 3 change triggers create insteand of update #359
Comments
I think the issue here is that I'm using
|
Thank you for reporting. Well, a "replacement strategy" phrasing implies deletion and re-creation. Some quick googling also points to comments like helm/helm#5281 (comment) saying that "… So, Kopf handles what actually happens on Kubernetes level — deletion and then creation. Internally, Kopf distinguishes between creation and upgrades by presence or absence of an annotation named So, you have to implement your own global state, accessed by e.g. resource names or namespaces+names. Then, put both on-creation and on-update handlers to the same function, and check for the existence internally. Conceptually, something like this: import kopf
RESOURCES = {}
@kopf.on.create(...)
@kopf.on.update(...)
def myresouce_changed_fn(namespace, name, **_):
key = f'{namespace}/{name}'
if key in RESOURCES:
print('it was an upgrade')
else:
print('it was a real creation')
RESOURCES[key] = ...
@kopf.on.delete(...)
def myresource_deleted(namespace, name, **_):
key = f'{namespace}/{name}'
if key in RESOURCES:
del RESOURCES[key] |
As a slightly more advanced solution, but also slightly more complex, you can utilise the recent configurable storages for "diff-bases" aka "essences" of the resources (available since 0.27rc6 — release candidates yet, as of 2020-05-12): import kopf
from typing import MutableMapping, Any, Optional
class ByNameDiffBaseStorage(kopf.DiffBaseStorage):
_items: MutableMapping[str, kopf.BodyEssence]
def __init__(self) -> None:
super().__init__()
self._items = {}
def fetch(self, *, body: kopf.Body) -> Optional[kopf.BodyEssence]:
key = f'{body.metadata.namespace}/{body.metadata.name}'
return self._items.get(key, None)
def store(self, *, body: kopf.Body, patch: kopf.Patch, essence: kopf.BodyEssence) -> None:
key = f'{body.metadata.namespace}/{body.metadata.name}'
self._items[key] = essence
@kopf.on.startup()
def configure(settings: kopf.OperatorSettings, **_):
settings.persistence.diffbase_storage = kopf.MultiDiffBaseStorage([
settings.persistence.diffbase_storage, # the default Kopf's storage
ByNameDiffBaseStorage(),
])
@kopf.on.create('zalando.org', 'v1', 'kopfexamples')
def create_fn(**_):
pass
@kopf.on.update('zalando.org', 'v1', 'kopfexamples')
def update_fn(**_):
pass
@kopf.on.delete('zalando.org', 'v1', 'kopfexamples')
def delete_fn(**_):
pass The magic happens in Note: I've made only a quick-test of this code, not the thorough testing. This is only a theory how the problem can be hacked. This code can lead to unexpected consequences, so better test it in an isolated cluster (e.g. minikube or kind or so). Two quite obvious problems:
One fancy effect:
PS: Perhaps, you also want to include the resource's kind/singular/plural/full name into the key, in case you have multiple resources served by the same operator. Otherwise, they can have the same "namespace/name" strings, and will collide with each other in memory. More info: |
Long story short
helm 3 updates trigger
@kopf.on.create
rather than@kopf.on.update
.Description
After a resource has been created using helm3 (haven't tested with helm2), and the definition changes, kopf is triggering the create function rather than update
These are the debug logs from helm
This is how my operator sees this update:
However, when I apply the same changes using `kubectl apply -f`, I get the expected result.
Environment
Python packages installed
The text was updated successfully, but these errors were encountered: