kr8s-org / kr8s

A batteries-included Python client library for Kubernetes that feels familiar for folks who already know how to use kubectl
https://kr8s.org
BSD 3-Clause "New" or "Revised" License
799 stars 43 forks source link

Some api resources are not found #482

Closed armand-AbsolutSensing closed 2 weeks ago

armand-AbsolutSensing commented 4 weeks ago

Which project are you reporting a bug for?

kr8s

What happened?

I notice that using kr8s to list some custom crds (helmrepositories and gitrepositories from flux project). I can found gitrepositories but not helmrepositories, event if it's working with kubectl.

for repository in kr8s.get('gitrepositories', namespace=kr8s.ALL):
    assert any(
        condition['type'] == 'Ready' and condition['status'] == 'True'
        for condition in repository.status['conditions']
    )
for helmrepository in kr8s.get('helmrepositories', namespace=kr8s.ALL):
    assert any(
        condition['type'] == 'Ready' and condition['status'] == 'True'
        for condition in helmrepository.status['conditions']
    )
self = <kr8s.Api object at 0x7d6dfec2d410>, kind = 'helmrepositories'

    async def async_lookup_kind(self, kind) -> tuple[str, str, bool]:
        """Lookup a Kubernetes resource kind."""
        from ._objects import parse_kind

        resources = await self.async_api_resources()
        kind, group, version = parse_kind(kind)
        if group:
            version = f"{group}/{version}"
        for resource in resources:
            # print(resource)
            if (not version or version in resource["version"]) and (
                kind == resource["name"]
                or kind == resource["kind"]
                or kind == resource["singularName"]
                or ("shortNames" in resource and kind in resource["shortNames"])
            ):
                print('1')
                if "/" in resource["version"]:
                    return (
                        f"{resource['singularName']}.{resource['version']}",
                        resource["name"],
                        resource["namespaced"],
                    )
                print('2')
                return (
                    f"{resource['singularName']}/{resource['version']}",
                    resource["name"],
                    resource["namespaced"],
                )
>       raise ValueError(f"Kind {kind} not found.")
E       ValueError: Kind helmrepositories not found.

../../../miniconda3/envs/PyInfra/lib/python3.11/site-packages/kr8s/_api.py:320: ValueError

After investigation it seems to be caused by them being both from the same group (source.toolkit.fluxcd.io) but gitrepositories is available in version v1(latest), v1beta2(deprecated), v1beta1(deprecated) and helmrepositories only in v1beta2(latest), v1beta1(deprecated) . When listing resources, the function async_api_resources will look for each group associated with theirs latest version (here v1) and get all the associated resource, ignoring the other version, so cannot found resource helmrepositories.

Anything else?

No response

jacobtomlinson commented 4 weeks ago

Thanks for raising this! Yup that's a bug that totally needs fixing. It looks like the specific section of code is here.

https://github.com/kr8s-org/kr8s/blob/721dc09cca5f9d202c3ddc9675d9c1e40ab5a75d/kr8s/_api.py#L573-L577

I think we need to look up all resources for all versions and return them all from async_api_resources().

The implication of doing this is that in places that use the [async_]api_resources() methods there will be duplicates across many versions so we need to implement sorting correctly.

https://github.com/kr8s-org/kr8s/blob/721dc09cca5f9d202c3ddc9675d9c1e40ab5a75d/kr8s/_api.py#L293

For example we would need to make sure that await api.lookup_kind("gitrepositories") returns the v1 version.