-
-
Notifications
You must be signed in to change notification settings - Fork 324
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Decouple Meta from k8s-openapi #385
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a good idea at the core of this that can make DynamicResource
usable. Left some comments on the new Meta trait, there is some work needed there IMO. That said, thanks a lot for this. You've found a huge lack in DynamicResource
, which is worth raising a bug about as well.
/// Types that know their metadata at compile time should select `Family = ()`. | ||
/// Types that require some information at runtime should select `Family` | ||
/// as type of this information. | ||
type Family: Send + Sync + 'static; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the crux of the PR. We are changing the Meta
trait to basically be our own, more practical, Resource
trait. I think that overall is positive; DynamicResource
, as you pointed out, just could not work in more than trivial situations without this change, and a blanket implementation of our trait of k8s_openapi::Resource + Metadata
objects is - in theory - easy to do.
A rename of the trait is probably in order to reflect what the trait now does. Not sure to what though.
The Family
type parameter here is definitely the most awkward implementation detail of the trait though. Ideally, I would like to avoid this, as it's making breaking changes to both kube::Resource
and kube::Api
(as well as making them more awkward).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding naming, Do you think the following makes sense?
- rename Meta to Resource
- rename Resource to RequestBuilder/QueryBuilder
- rename Family to RuntimeTypeInformation (long name, but anyway users will rarely interact with it)
I tried to make sure that kube::Api
public API was not modified (if K
has all necessary information at compile-time, Api::all
and Api::namepsaced
are still provided). Did I miss something? I will also add similar backward-compatible constructors to the Resource
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this has a lot more potential now that it's shown that we don't need to break Api
or Resource
, although I will leave some comments on the implementation inlined elsewhere.
Let's not worry about the names of those three yet (it'll make it super confusing to review, so we can change them later). Although I think in theory the first two are fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some high level comments / questions
Static(&'static str), | ||
/// Should be used when string is only known at runtime | ||
Dynamic(Arc<str>), | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This string wrapper does feel like a pretty complicated thing to expose in an interface. Could you explain what it's trying to optimise for? The Arc in there feels particularly confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's purely an optimization to make cloning less expensive, especially when GVK is known at compile-time.
Do you think it should be replaced by a plain String
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's only a handful of strings that gets cloned once, then I would worry more about the prettiness of the api more, if it's happening all the time, then it's definitely a reasonable optimization.
I think it's probably a smart thing to do internally (now that GVK has a simpler constructor), but I don't think we should expose StringRef
to the world.
Also, curious to the tradeoff of Arc<str>
vs just String
inside Dynamic
. It feels like this would just be a ref to the apps' owned String, with atomic because it's used in threads? Maybe we can use Into<String>
in the constructor and turn it to a String in the enum instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll change StringRef
to be private (as well as GVK fields) and provide two constructors (static and dynamic) instead.
examples/generic_watcher.rs
Outdated
}; | ||
|
||
let client = Client::try_default().await?; | ||
let api = Api::<DynamicObject>::all_with(client, &erased_kind); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this is achievable, but ideally, I feel like this could look like:
let gvk = GroupVersionKind::group(group).version(version).kind(kind);
let api: Api<DynamicObject> = gvk.into_api(client);
which looks very similar to the current DynamicResource
, so maybe you don't need the separate ErasedKind
(or GroupVersionKind
as i suggested calling it).
Don't worry about breaking DynamicResource
; it already doesn't work.
By the way, it seems that CI does not check that kube is able to compile without warnings. |
{ | ||
stream | ||
.map_ok(move |obj| stream::iter(mapper(obj).into_iter().map(Ok))) | ||
.try_flatten() | ||
} | ||
|
||
/// Enqueues the object itself for reconciliation | ||
pub fn trigger_self<S>(stream: S) -> impl Stream<Item = Result<ObjectRef<S::Ok>, S::Error>> | ||
pub fn trigger_self<S, F>(stream: S, family: F) -> impl Stream<Item = Result<ObjectRef<S::Ok>, S::Error>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is slight breakage in a low-level API. Do you think it's OK not to provide separate trigger_self
and trigger_self_with
functions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally, yes. I think this is ok.
Seems that the automatic merge has broken things a bit. I will rebase on the master. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left only a few tiny nits. It's a complex one, and sorry it's taken me this long to get to it, but it is really appreciated.
{ | ||
stream | ||
.map_ok(move |obj| stream::iter(mapper(obj).into_iter().map(Ok))) | ||
.try_flatten() | ||
} | ||
|
||
/// Enqueues the object itself for reconciliation | ||
pub fn trigger_self<S>(stream: S) -> impl Stream<Item = Result<ObjectRef<S::Ok>, S::Error>> | ||
pub fn trigger_self<S, F>(stream: S, family: F) -> impl Stream<Item = Result<ObjectRef<S::Ok>, S::Error>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally, yes. I think this is ok.
Sorry, I tried to resolve conflicts last nights, thought I did it. The conflicts were all around type parameters where I had added |
Finally merged! Thanks a lot for all the work here :D I did discover one small p'tietoau quirk in #464. so will hold off on the release for a little bit while thinking about it, but it's pretty minor, and non-blocking. However, if you have time to look it'd be really appreciated. |
Before releasing, I think we should discuss renaming the associated type For the changelog, I think we should briefly mention what needs to be changed to update when it's not obvious. This also helps users to understand the scope (if they're affected or not). If I'm understanding correctly, this change doesn't affect many, but the current changelog looks intimidating because it's unclear. I think most users are unfamiliar with |
Yeah, I agree with that. I mostly wrote out the things as I saw them for myself. Wasn't even sure if many people have read this PR, as it's been silently sitting in the background for 3 months :-) Naming. I'll open a new issue on this. |
Released in 0.52.0 😅 |
This PR changes
kube::api::Meta
so that it no longer depends onk8s-openapi
.TODO:
debug
generic_watcher
not working (upd: fixed)