use crate::{Context, CoreDB, CoreDBSpec, CoreDBStatus, Metrics, COREDB_FINALIZER};
use assert_json_diff::assert_json_include;
use futures::pin_mut;
use http::{Request, Response};
use hyper::{body::to_bytes, Body};
use kube::{Client, Resource, ResourceExt};
use prometheus::Registry;
use std::sync::Arc;
use tokio::task::JoinHandle;
use tower_test::mock::{self, Handle};
impl CoreDB {
pub fn test() -> Self {
let mut d = CoreDB::new("testdb", CoreDBSpec::default());
d.meta_mut().namespace = Some("testns".into());
d.meta_mut().uid = Some("752d59ef-2671-4890-9feb-0097459b18c8".into());
d.spec.replicas = 1;
d
}
pub fn finalized(mut self) -> Self {
self.finalizers_mut().push(COREDB_FINALIZER.to_string());
self
}
pub fn with_status(mut self, status: CoreDBStatus) -> Self {
self.status = Some(status);
self
}
}
pub struct ApiServerVerifier(Handle<Request<Body>, Response<Body>>);
impl ApiServerVerifier {
pub fn handle_finalizer_creation(self, coredb_: &CoreDB) -> JoinHandle<()> {
let handle = self.0;
let coredb = coredb_.clone();
tokio::spawn(async move {
pin_mut!(handle);
let (request, send) = handle.next_request().await.expect("service not called");
assert_eq!(request.method(), http::Method::PATCH);
assert_eq!(
request.uri().to_string(),
format!(
"/apis/coredb.io/v1alpha1/namespaces/testns/coredbs/{}?",
coredb.name_any()
)
);
let expected_patch = serde_json::json!([
{ "op": "test", "path": "/metadata/finalizers", "value": null },
{ "op": "add", "path": "/metadata/finalizers", "value": vec![COREDB_FINALIZER] }
]);
let req_body = to_bytes(request.into_body()).await.unwrap();
let runtime_patch: serde_json::Value =
serde_json::from_slice(&req_body).expect("valid coredb from runtime");
assert_json_include!(actual: runtime_patch, expected: expected_patch);
let response = serde_json::to_vec(&coredb.finalized()).unwrap(); send.send_response(Response::builder().body(Body::from(response)).unwrap());
})
}
pub fn handle_coredb_patch(self, coredb_: &CoreDB) -> JoinHandle<()> {
let handle = self.0;
let coredb = coredb_.clone();
tokio::spawn(async move {
pin_mut!(handle);
let (request, send) = handle
.next_request()
.await
.expect("Kube API called to PATCH CoreDB");
assert_eq!(request.method(), http::Method::PATCH);
assert_eq!(
request.uri().to_string(),
format!(
"/apis/coredb.io/v1alpha1/namespaces/testns/coredbs/{}/status?&force=true&fieldManager=cntrlr",
coredb.name_any()
)
);
let req_body = to_bytes(request.into_body()).await.unwrap();
let json: serde_json::Value =
serde_json::from_slice(&req_body).expect("patch_status object is json");
let status_json = json.get("status").expect("status object").clone();
let status: CoreDBStatus = serde_json::from_value(status_json).expect("contains valid status");
assert!(
status.running,
"CoreDB::test says the status isn't running, but it was expected to be running."
);
let response = serde_json::to_vec(&coredb.with_status(status)).unwrap();
send.send_response(Response::builder().body(Body::from(response)).unwrap());
let (request, send) = handle
.next_request()
.await
.expect("Kube API called to PATCH StatefulSet");
assert_eq!(request.method(), http::Method::PATCH);
assert_eq!(
request.uri().to_string(),
format!(
"/apis/apps/v1/namespaces/testns/statefulsets/testdb?&force=true&fieldManager=cntrlr"
)
);
send.send_response(Response::builder().body(request.into_body()).unwrap());
let (request, send) = handle
.next_request()
.await
.expect("Kube API called to PATCH Service");
assert_eq!(request.method(), http::Method::PATCH);
assert_eq!(
request.uri().to_string(),
format!("/api/v1/namespaces/testns/services/testdb?&force=true&fieldManager=cntrlr")
);
send.send_response(Response::builder().body(request.into_body()).unwrap());
})
}
}
impl Context {
pub fn test() -> (Arc<Self>, ApiServerVerifier, Registry) {
let (mock_service, handle) = mock::pair::<Request<Body>, Response<Body>>();
let mock_client = Client::new(mock_service, "default");
let registry = Registry::default();
(
Arc::new(Self {
client: mock_client,
metrics: Metrics::default().register(®istry).unwrap(),
diagnostics: Arc::default(),
}),
ApiServerVerifier(handle),
registry,
)
}
}