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

Create an `APIObject` based class from a `CustomResourceDefinition` #457

Open jacobtomlinson opened 1 month ago

jacobtomlinson commented 1 month ago

We can use the CustomResourceDefinition objects to create/update/delete Custom Resource Definitions. But if we want to create the Custom Resources themselves we need to call new_class() with the name of the CRD and some options to generate a class that we can use to create resources.

It would be nice if CustomResourceDefinition had a utility method to do this for us automatically.

For example if we start by making a new CRD.

from kr8s.objects import CustomResourceDefinition

# Define a custom resource definition for `shirts.stable.example.com`
shirts_crd = CustomResourceDefinition(
    {
        "metadata": {"name": "shirts.stable.example.com"},
        "spec": {
            "group": "stable.example.com",
            "scope": "Namespaced",
            "names": {"plural": "shirts", "singular": "shirt", "kind": "Shirt"},
            "versions": [
                {
                    "name": "v1",
                    "served": True,
                    "storage": True,
                    "schema": {
                        "openAPIV3Schema": {
                            "type": "object",
                            "properties": {
                                "spec": {
                                    "type": "object",
                                    "properties": {
                                        "color": {"type": "string"},
                                        "size": {"type": "string"},
                                    },
                                }
                            },
                        }
                    },
                }
            ],
        },
    }
)
# Create the CRD
shirts_crd.create()

Now we have a CRD for shirts.stable.example.com/v1 we might want to make a new Shirt resource. Currently we would need to use new_class() and pass a lot of the same information that we passed to the CRD.

from kr8s.objects import new_class

Shirt = new_class("shirts.stable.example.com/v1", namespaced=True)  # If Shirt was scalable this would be even more complex

Instead we could add a method to CustomResourceDefinition to do this for us.

# Create an object class for `shirts.stable.example.com/v1`
Shirt = shirts_crd.as_class(version="v1")  # The version could be optional and just use the first as a default

Alternatively we could update new_class() to accept a CRD.

from kr8s.objects import new_class

Shirt = new_class(shirts_crd)  # Would need to think about how to handle which schema version is used

Then we can finally define and create a Shirt.

# Define a shirt
my_shirt = Shirt(
    {
        "metadata": {"name": "myshirt"},
        "spec": {
            "color": "red",
            "size": "XL",
        },
    }
)
my_shirt.create()