lightkube icon indicating copy to clipboard operation
lightkube copied to clipboard

Need simpler way to remove labels.

Open averma-canonical opened this issue 2 years ago • 4 comments

The current method to remove a label looks somewhat convoluted.

label_to_remove = label.replace('/','~1')

patch = [{"op": "remove", "path": label_to_remove}]

client.patch(
                res=ServiceAccount,
                name=resource_name,
                namespace=namespace,
                obj=patch,
                patch_type=PatchType.JSON,
            )

Request is to add a cleaner dedicated api to remove a label on a resource, something akin to

client.remove_label(
                res=ServiceAccount,
                name=resource_name,
                namespace=namespace,
                label=label_full_path_unmodified
            )

Along the same lines, a dedicated api to label a resource would also be useful. For e.g. for labeling a service account

client.set_label(
                res=ServiceAccount,
                name=resource_name,
                namespace=namespace,
                label=label_full_path_unmodified
            )

averma-canonical avatar Mar 21 '23 14:03 averma-canonical

To add to this, my intuition was that there'd be a declarative way of doing this, but @averma-canonical didn't find success there. If there's another way that's preferred, maybe an addition to the docs would help.

ca-scribner avatar Mar 21 '23 15:03 ca-scribner

Thanks @ca-scribner. Sharing the example Andrew mentioned for reference purpose.

r = client.get(res=ServiceAccount, name=resource_name, namespace=namespace)

del r.metadata.labels[label]

client.patch(res=ServiceAccount, obj=r, name=resource_name, namespace=namespace)

r2 = client.get(res=ServiceAccount, name=resource_name, namespace=namespace)

assert label not in r2.metadata.labels

Assertion in the above code block fails which was not expected.

averma-canonical avatar Mar 22 '23 11:03 averma-canonical

You can use the default patch type (PatchType.STRATEGIC). Example with a config map:

from lightkube import Client
from lightkube.resources.core_v1 import ConfigMap
from lightkube.models.meta_v1 import ObjectMeta

# create a new config map without labels
config = ConfigMap(
    metadata=ObjectMeta(name='my-config', namespace='default'),
    data={'key1': 'value1', 'key2': 'value2'}
)

client = Client()
cm = client.create(config)
assert cm.metadata.labels is None  # no labels right now

To add a label:

patch = {'metadata': {'labels': {'label1': 'value1'}}}
cm = client.patch(ConfigMap, name='my-config', obj=patch)
assert 'label1' in cm.metadata.labels

To remove the label:

patch = {'metadata': {'labels': {'label1': None}}}
cm = client.patch(ConfigMap, name='my-config', obj=patch)
assert cm.metadata.labels is None

Note that you cannot use del to remove the label as this is a patch and what is not sent is considered unchanged. You need to pass the label with a value of None instead. See documentation.

To me, It seems simple enough to not deserve a dedicated client method. Maybe you want to add an example in the documentation?

gtsystem avatar Mar 25 '23 10:03 gtsystem

I added an example in the documentation, however I'm keeping this open as it could still be nice to design something to easily modify labels and annotations (better even with a single call)

gtsystem avatar Oct 30 '23 16:10 gtsystem