Skip to content
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

Implement client native object reference fetching #1511

Merged
merged 1 commit into from
Jun 11, 2024

Conversation

Danil-Grigorev
Copy link
Member

@Danil-Grigorev Danil-Grigorev commented Jun 4, 2024

Motivation

One of the ways custom resources are declaring dependency on each other, is by providing and ObjectReference field. Having one, still requires to manually prepare an appropriate client/api setup, extract namespace and name and validate the kind, api_version fields. This PR allows to make ObjectReferences native to client, and simplify their use. Additionally it provides similar handling for OwnerReferences.

Solution

Implement a client.fetch method, allowing for the use of the following syntax:

// Actual ObjectReference content is intended to come from a CR
let svc: Service = client.fetch(&ObjectReference::default())
let node: Node = client.fetch(&OwnerReference::default()).await?;
let pod: Pod = client.fetch(&OwnerReference::default().within("default".into())).await?;
// Still the same pod
let pod: DynamicObject = client.fetch(&pod.object_ref(&())).await?;
let local_ref = LocalObjectReference {name: svc.name_any().into()};
let svc: Service = client.fetch(&local_ref.within(svc.namespace())).await?;

Current implementation also constants ability for specifying namespace for the OwnerReference from the resource. This is only allowed on non-cluster scoped resources.

@Danil-Grigorev Danil-Grigorev force-pushed the unstable-client-fetch-reference branch 2 times, most recently from d125153 to 2057c6b Compare June 4, 2024 16:02
Copy link

codecov bot commented Jun 4, 2024

Codecov Report

Attention: Patch coverage is 78.70370% with 23 lines in your changes missing coverage. Please review.

Project coverage is 75.1%. Comparing base (5aa8f83) to head (191435e).

Additional details and impacted files
@@           Coverage Diff           @@
##            main   #1511     +/-   ##
=======================================
+ Coverage   75.0%   75.1%   +0.2%     
=======================================
  Files         78      78             
  Lines       6872    6980    +108     
=======================================
+ Hits        5151    5240     +89     
- Misses      1721    1740     +19     
Files Coverage Δ
kube-core/src/gvk.rs 75.5% <53.4%> (-7.1%) ⬇️
kube-client/src/client/client_ext.rs 84.5% <82.8%> (-3.6%) ⬇️

... and 4 files with indirect coverage changes

@Danil-Grigorev Danil-Grigorev force-pushed the unstable-client-fetch-reference branch from 2057c6b to a051537 Compare June 4, 2024 16:10
@Danil-Grigorev Danil-Grigorev changed the title Implement client native object reference fetching [WIP] Implement client native object reference fetching Jun 5, 2024
@Danil-Grigorev
Copy link
Member Author

Danil-Grigorev commented Jun 5, 2024

Marking this a WIP, as I’m trying to expand it to OwnerReferences, and impl Into<Option<smth>> is not cooperating with linter or Option into Option (generally looks like is not needed).

Edit: Updated, does not look ideal, but would like to know WDYT.

@Danil-Grigorev Danil-Grigorev force-pushed the unstable-client-fetch-reference branch 3 times, most recently from 3650406 to 37e6104 Compare June 5, 2024 21:01
@Danil-Grigorev Danil-Grigorev changed the title [WIP] Implement client native object reference fetching Implement client native object reference fetching Jun 5, 2024
Copy link
Member

@clux clux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i like the idea of this. possible suggestion included.

kube-client/src/client/client_ext.rs Outdated Show resolved Hide resolved
kube-client/src/client/client_ext.rs Outdated Show resolved Hide resolved
@clux clux added changelog-add changelog added category for prs unstable feature that unstable feature gating labels Jun 5, 2024
@Danil-Grigorev Danil-Grigorev force-pushed the unstable-client-fetch-reference branch 2 times, most recently from aaa56eb to 3aad40b Compare June 6, 2024 19:04
@Danil-Grigorev Danil-Grigorev changed the title Implement client native object reference fetching [WIP] Implement client native object reference fetching Jun 6, 2024
@Danil-Grigorev Danil-Grigorev force-pushed the unstable-client-fetch-reference branch 5 times, most recently from 3ef3838 to 2f1e3de Compare June 7, 2024 09:13
@Danil-Grigorev Danil-Grigorev changed the title [WIP] Implement client native object reference fetching Implement client native object reference fetching Jun 7, 2024
@Danil-Grigorev Danil-Grigorev force-pushed the unstable-client-fetch-reference branch from 2f1e3de to 542aa7b Compare June 7, 2024 09:23
kube-client/src/client/client_ext.rs Outdated Show resolved Hide resolved
Comment on lines 53 to 57
/// Reference resolver for a specified namespace
pub trait NamespacedRef<K>: ObjectUrl<K> {
/// Resolve reference in the provided namespace
fn within(&self, namespace: String) -> impl ObjectRef<K>;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this will be a new required trait to use for people doing dynamic object ref -> object url inferences.

I think this is a good solution, but probably one that makes us perhaps want to consider a prelude down the road.

Comment on lines +59 to +69
impl<K> ObjectUrl<K> for ObjectReference
where
K: Resource,
{
fn url_path(&self) -> String {
url_path(
&ApiResource::from_gvk(&self.clone().into()),
self.namespace.clone(),
)
}
}
Copy link
Member

@clux clux Jun 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conversion here makes sense, but wondering if will it work for other "objectreference-like things" with less information. In particular, would we be able to handle:

not saying we need to, but it's good to know the limits of the design. what would we need to do support LocalObjectReference? Would it even make sense in this design?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that both of them are quite ambiguous. I pushed a change which tries to support for both, but for LocalObjectReference there is a need of a real field which uses it, which can come only from CR. Also the definitions are open to interpretation. TypedLocalObjectReference has an api_group which is confusing, as it is different sometimes from api_version (which is actually group/version always). Forcing some definition there seems a bit questionable to me, need to think it through. Here are some examples:

I’d like to try if the exported trait can be implemented externally, and if possibly wrapping a LocalObjectReference and implementing the NamespaceRef trait for the wrapped type, providing From implementation + some kopium changes to recognize selectively LocalObjectReference can be a thing.

Copy link
Member

@clux clux Jun 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LocalObjectReference there is a need of a real field which uses it

i found one use-case on PodSpec::image_pull_secrets which implicitly references Secret object as per kubernetes docs. this is more awkward than I expected because it's not the same resource as the one it was found on.

TypedLocalObjectReference has an api_group which is confusing

..yeah. if that's the case then it's probably not super important to worry about it. people can write converters from one object ref to the one they want to disambiguate. that said though, i would say the first example there is wrong. apigroup should be just the group, and the usage of TypedLocalObjectReference is an indication that people should do discovery to make the version concrete.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So after some consideration I removed the use of TypedLocalObjectReference. This ambiguity translates to kube-rs as well. What the library needs, I think, is a rough equivalent of CR scheme.go, where a type registers itself and provides a bunch of helpers, some of them using discovery client, some of them in-memory. This would allow to look up the version for the GroupKind the TypedLocalObjectReference represents, probably even without using discovery, as a key from GroupKind<->GroupVersionKind mapping.

I’d also love to have this bits being autogenerated by the “derive” feature sometime in the future. WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think this is fair. The scheme registration I am not sure how it would work, but some user input feels necessary to solve the ambiguity. Happy to look at PRs or help sketch on issues for it (hard to envision it all from my POV now).

}
}

impl<K> ObjectUrl<K> for OwnerReference
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are 2 more types that effectively we could implement for free as they generally have enough information:

perhaps good to do one/two of those to show the system is extensible enough.

Comment on lines +433 to +473
let ca: ClusterRole = client
.fetch(&ObjectReference {
kind: Some(ClusterRole::kind(&()).into()),
api_version: Some(ClusterRole::api_version(&()).into()),
name: Some("cluster-admin".into()),
..Default::default()
})
.await?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be good to see have an error test as well, to see what happens if people type inference the wrong thing (e.g. :Service with ObjectRef data for a ClusterRole say). might not be able to do something useful, but if we could reduce confusion, then that's less issues for us down the line.

@Danil-Grigorev Danil-Grigorev force-pushed the unstable-client-fetch-reference branch 2 times, most recently from a269227 to ea06d7c Compare June 10, 2024 08:01
@Danil-Grigorev Danil-Grigorev force-pushed the unstable-client-fetch-reference branch from ea06d7c to 191435e Compare June 10, 2024 08:22
Copy link
Member

@clux clux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is very useful, and provides an elegant way to solve a generic problem. Thanks a lot for thinking up this (and making fetch happen).

Any follow-up stories feel free to write up if you have any, I will write up a few tomorrow; client_ext module setup (file is getting big), and a prelude sketch. If you have any other things you like to clean up feel free to, but I am at least happy to send this out as is (under the unstable feature).

@clux clux added this to the 0.92.0 milestone Jun 10, 2024
@clux clux merged commit 9df1b43 into kube-rs:main Jun 11, 2024
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
changelog-add changelog added category for prs unstable feature that unstable feature gating
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants