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
Write an in-memory apiserver #1108
Comments
NB: Prior discussion around It is currently pretty easy to do this for a small amount of integration tests. We use this approach, and it does not require mock clients, but it does force us to consider how some tests might interact with others (limiting how deeply we can use this approach). This issue is instead trying to turn more complicated integration tests into true unit tests for users. Both style of tests have a place. |
A perhaps more promising, and less work-involving way forward here for integration tests is to lean on; https://github.com/kubernetes-sigs/kwok/
We have not done any particular testing of this yet (and it's currently in a super early release), but noting this down. Have closed our older kube-test / envtest proposals in the past. |
Thanks for the suggestion on using KWOK @clux. It's working really well on my tests, and I spin up multiple clusters of it using testcontainers. If you would like I could create a PR adding documentation about it. |
What problem are you trying to solve?
A thing that continually comes up in the concept of controller testing is being able to run the reconciler and verify that it does the right thing.
In complex scenarios this is difficult for users to do right now without a semi-functioning apiserver.
We currently recommend using a mock client:
and pass that into the reconciler's context where we intercept the api calls and return some reasonable information. See controller-rs's fixtures.rs and controller.rs for test invocations.
It is perfectly possible to do that in tests (and we do) like this particular wrapper around
tower_test::mock::Handle<Request<Body>, Response<Body>>
responding to anEvent
being POSTed, while also checking some properties of that data:
The problem with this approach is that:
Request
/Body
/Response
/serde_json::Value
fiddling)Describe the solution you'd like
Create a dumb, in-memory apiserver that does the bare minimum of what the apiserver does,
and presents a queryable interface that can give us what is in "its database" through some type downcasting.
This server could treat every object as a
DynamicObject
storing what it sees in aHashMap<ObjectRef, DynamicObject>
as an initial memory backing.If this was made pluggable into
tower_test::mock
, users can hook it into tests around a reconciler without the tests failing due to bad apiserver responses, without having to have users know all the ins and outs of apiserver mechanics (and crucially without giving them the opportunity to get this wrong).Implementation
We would need at the very least implement basic functionality around
metadata
on objects:creationTimestamp
,uid
,resourceVersion
,generation
, populatename
fromgenerateName
creationTimestamp
/uid
/resource_version
/generation
HashMap
ownerReferences
Implementing create/replace/delete/get calls on resources plus most calls on subresources "should not be too difficult" to do in this context and will benefit everyone.
The real problem here would be implementing
patch
in a sensible way:Some of this sounds very hard, but it's possible some of it can be cobbled together using existing ecosystem pieces like:
Anyway, just thought I would write down my thoughts on this. It feels possible, but certainly a bit of a spare time project. If anyone wants this, or would like to tackle this, let us know. I have too much on my plate for something like this right now, but personally I would love to have something like this if it can be done in a sane way.
Documentation, Adoption, Migration Strategy
can be integrated into controller-rs plus the controller guide on kube.rs as a start.
The text was updated successfully, but these errors were encountered: