Arnavion / k8s-openapi

Rust definitions of the resource types in the Kubernetes client API
Apache License 2.0
386 stars 41 forks source link

need impl Metadata for PodTemplateSpec #157

Open waynr opened 1 month ago

waynr commented 1 month ago

I'm attempting to write code that is generic over types that implement k8s_openapi::Metadata<Ty = ObjectMeta>. PodTemplateSpec could fit into this category but doesn't. When I try to write an impl of my trait with a bound on k8s_openapi::Metadata AND try to impl it directly for PodTemplateSpec, I get a compiler error indicating not that there is an existing implementation conflict, but that there could in a future release be an impl Metadata<Ty = ObjectMeta> for PodTemplateSpec, which doesn't leave me with any particularly good options other than to discard the implementation of my trait bounded by this crate's Metadata and instead write discrete impls for each type that I use...or write my own macro for it.

I think the simplest solution for me would be if it were possible to generate an impl Metadata for PodTemplateSpec in this crate. Is that something the maintainers would be open to? It's not obvious to me where this should go since the existing impl Metadata for <TYPE> seems to be based on top-level k8s API objects that have an api version, kind, group, etc. Otherwise I would have just opened a PR right away.

Arnavion commented 1 month ago

It's not obvious to me where this should go since the existing impl Metadata for seems to be based on top-level k8s API objects that have an api version, kind, group, etc.

Correct. Metadata is for resource types that have a metadata field, and resource types are types with an API version and group, which PodTemplateSpec is not.

If we want a trait for "any type that has a metadata field regardless of whether it's a resource type or not, it would have to be a new trait.

What exactly is the function you want to write that should work with Metadata impls as well as with PodTemplateSpec ? There might be a different way to do what it does, eg by taking ObjectMeta directly instead of the type that contains it.

waynr commented 1 month ago

I'm attempting to write traits that look like this:

pub trait Annotations {
    fn push_annotation(self, key: impl Into<String>, value: impl Into<String>) -> Self;

    fn append_annotations<'a>(self, kvs: impl Iterator<Item = (&'a String, &'a String)>) -> Self;
}

In most cases where I am adding annotations (or other attributes, this is just a short example) I want to add them to the PodTemplateSpec as well as the top-level resource (eg Deployment, StatefulSet, Job).

waynr commented 1 month ago

I wonder if it would be better to discard my impl<T: k8s_openapi::Metadata<Ty = ObjectMeta>> Annotations for T and write macros for my trait impls such that adding the annotations/labels/whatever to the top-level resource object automatically adds them to the pod template spec :thinking:

Arnavion commented 1 month ago

You can either ditch the builder trait idea and make it a fn that takes &mut Metadata:

fn push_annotations(&mut Metadata, key: ...) { ... }

push_annotations(&mut pod.metadata);

... or you can keep the trait idea but impl it for Metadata:

trait Annotations {
    fn push_annotation(&mut self, key: ...);
}

impl Annotations for Metadata { fn push_annotation(&mut self, key: ...) { self.annotations.push(key, ...); } }

... or keep your original trait and impl it for individual concrete types that you want to use it with.