cdk8s-team / cdk8s

Define Kubernetes native apps and abstractions using object-oriented programming
https://cdk8s.io
Apache License 2.0
4.29k stars 290 forks source link

Add ability to create objects by loading synthesized YAMLs #352

Closed mcouthon closed 3 years ago

mcouthon commented 3 years ago

Description of the feature or enhancement:

After having created k8s YAMLs by synthesizing Python Charts, I'd like to be able to do the reverse — create Python objects by loading those same YAMLs.

Use Case:

This would be useful for tests/validation that will go over the YAMLs, and would avoid code like this:

deployment_object = yaml.safe_load(open(name))
deployment_full_name = deployment_object["spec"]["template"]["metadata"]["name"]

Proposed Solution:

I envision the code looking like:

with open(path_to_yaml, "r") as f:
    manifest = yaml.safe_load(f)

k8s_object = k8s.load_from_yaml(manifest)

# access any fields, for example
print(k8s_object.spec.template.metadata.name)

Other:


This is a :rocket: Feature Request

eladb commented 3 years ago

@mcouthon Are you familiar with the Include construct?

mcouthon commented 3 years ago

Thanks, @eladb, I wasn't familiar with it. But it's either not what I'm looking for, or else I'm not sure how to use it.

I created this minimal example:

from cdk8s import Include, Chart, App

class B(Chart):
    def __init__(self, scope, name):
        super().__init__(scope, name)

        dep = Include(self, name="dep", url="<PATH_TO_YAML>")

a = App()
b = B(a, "b")

Now I can indeed call b.to_json() and get a dict representing the contents of my YAML, or I can synth the chart, but I don't have a meaningful Python object in either b or dep, that I can do something like dep.metadata.name with.

eladb commented 3 years ago

@mcouthon wrote:

but I don't have a meaningful Python object in either b or dep, that I can do something like dep.metadata.name with.

dep.api_objects should return a list of ApiObjects which you can then interact with. For example, they all have a name field that includes the object's name.

mcouthon commented 3 years ago

Unfortunately, it doesn't seem to work. I've added to the above example:

class B(Chart):
    def __init__(self, scope, name):
        super().__init__(scope, name)

        dep = Include(self, name="dep", url="<PATH_TO_YAML>")
        print(dir(dep))
        print(dep.api_objects)

And got this:

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__jsii_ifaces__', '__jsii_ref__', '__jsii_type__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_on_prepare', '_on_synthesize', '_on_validate', 'to_string']
Traceback (most recent call last):
  File "XXX", line 12, in <module>
    b = A(a, "bla")
  File "XXX/lib/python3.8/site-packages/jsii/_runtime.py", line 69, in __call__
    inst = super().__call__(*args, **kwargs)
  File "XXX", line 9, in __init__
    print(dep.api_objects)
AttributeError: 'Include' object has no attribute 'api_objects'
eladb commented 3 years ago

Sorry, this was recently added in 0.31.0

mcouthon commented 3 years ago

Oh, sweet! I'm checking it now.

mcouthon commented 3 years ago

Alright, so now api_objects is indeed working. It's not exactly what I envisioned (a full fledged object, with all of the nested options, etc), but it's good enough for getting some basic information. Is there any option to expand the ApiObject that's returned here? For example, I see that ApiObjectMetadata can have additional info like labels and annotations, but when I look at the metadata object returned by dep.api_objects[0], I only see name in the metadata (although the underlying YAML definitely has more details in the metadata).

eladb commented 3 years ago

Metadata mutation will be supported soon and we have a roadmap item to cover inspection and mutation of api objects as well.

mcouthon commented 3 years ago

Ok, that's great. Thanks for the super quick help, @eladb 🙏 I'll close this for now, and follow the roadmap.