use crate::Client;
use crate::error::Result;
use crate::resource::Resource;
use serde_json::Value;
use std::collections::HashMap;
pub type BackgroundQueue = HashMap<String, Value>;
pub type BackgroundTask = crate::models::BackgroundTask;
pub type BackgroundWorker = HashMap<String, Value>;
pub type DataFile = crate::models::DataFile;
pub type DataSource = crate::models::DataSource;
pub type Job = crate::models::Job;
pub type ObjectChange = crate::models::ObjectChange;
pub type ObjectType = crate::models::ObjectType;
pub type BackgroundTasksApi = Resource<crate::models::BackgroundTask>;
pub type DataFilesApi = Resource<crate::models::DataFile>;
pub type DataSourcesApi = Resource<crate::models::DataSource>;
pub type JobsApi = Resource<crate::models::Job>;
pub type ObjectChangesApi = Resource<crate::models::ObjectChange>;
pub type ObjectTypesApi = Resource<crate::models::ObjectType>;
#[derive(Clone)]
pub struct CoreApi {
client: Client,
}
impl CoreApi {
pub(crate) fn new(client: Client) -> Self {
Self { client }
}
pub async fn background_queues(&self) -> Result<BackgroundQueue> {
self.client.get("core/background-queues/").await
}
pub async fn background_queue(&self, name: &str) -> Result<BackgroundQueue> {
self.client
.get(&format!("core/background-queues/{}/", name))
.await
}
pub fn background_tasks(&self) -> BackgroundTasksApi {
Resource::new(self.client.clone(), "core/background-tasks/")
}
pub async fn background_workers(&self) -> Result<BackgroundWorker> {
self.client.get("core/background-workers/").await
}
pub async fn background_worker(&self, name: &str) -> Result<BackgroundWorker> {
self.client
.get(&format!("core/background-workers/{}/", name))
.await
}
pub fn data_files(&self) -> DataFilesApi {
Resource::new(self.client.clone(), "core/data-files/")
}
pub fn data_sources(&self) -> DataSourcesApi {
Resource::new(self.client.clone(), "core/data-sources/")
}
pub fn jobs(&self) -> JobsApi {
Resource::new(self.client.clone(), "core/jobs/")
}
pub fn object_changes(&self) -> ObjectChangesApi {
Resource::new(self.client.clone(), "core/object-changes/")
}
pub fn object_types(&self) -> ObjectTypesApi {
Resource::new(self.client.clone(), "core/object-types/")
}
pub async fn enqueue_task(&self, id: &str) -> Result<BackgroundTask> {
self.client
.post(&format!("core/background-tasks/{}/enqueue/", id), &())
.await
}
pub async fn stop_task(&self, id: &str) -> Result<BackgroundTask> {
self.client
.post(&format!("core/background-tasks/{}/stop/", id), &())
.await
}
pub async fn requeue_task(&self, id: &str) -> Result<BackgroundTask> {
self.client
.post(&format!("core/background-tasks/{}/requeue/", id), &())
.await
}
pub async fn delete_task(&self, id: &str) -> Result<BackgroundTask> {
self.client
.post(&format!("core/background-tasks/{}/delete/", id), &())
.await
}
pub async fn sync_data_source(&self, id: u64) -> Result<DataSource> {
self.client
.post(&format!("core/data-sources/{}/sync/", id), &())
.await
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ClientConfig;
use httpmock::prelude::*;
use serde_json::json;
fn test_client() -> Client {
let config = ClientConfig::new("https://netbox.example.com", "token");
Client::new(config).unwrap()
}
fn mock_client(server: &MockServer) -> Client {
let config = ClientConfig::new(server.base_url(), "test-token");
Client::new(config).unwrap()
}
fn assert_path<T>(resource: Resource<T>, expected: &str)
where
T: serde::de::DeserializeOwned,
{
let paginator = resource.paginate(None).unwrap();
assert_eq!(paginator.next_url(), Some(expected));
}
#[test]
fn core_accessors_return_expected_paths() {
let api = CoreApi::new(test_client());
assert_path(api.background_tasks(), "core/background-tasks/");
assert_path(api.data_files(), "core/data-files/");
assert_path(api.data_sources(), "core/data-sources/");
assert_path(api.jobs(), "core/jobs/");
assert_path(api.object_changes(), "core/object-changes/");
assert_path(api.object_types(), "core/object-types/");
}
#[cfg_attr(miri, ignore)]
#[tokio::test]
async fn task_actions_use_expected_paths() {
let server = MockServer::start();
let client = mock_client(&server);
let enqueue_mock = server.mock(|when, then| {
when.method(POST)
.path("/api/core/background-tasks/abc123/enqueue/");
then.status(200).json_body(json!({}));
});
let _ = client.core().enqueue_task("abc123").await;
enqueue_mock.assert();
let stop_mock = server.mock(|when, then| {
when.method(POST)
.path("/api/core/background-tasks/task-id/stop/");
then.status(200).json_body(json!({}));
});
let _ = client.core().stop_task("task-id").await;
stop_mock.assert();
let requeue_mock = server.mock(|when, then| {
when.method(POST)
.path("/api/core/background-tasks/xyz/requeue/");
then.status(200).json_body(json!({}));
});
let _ = client.core().requeue_task("xyz").await;
requeue_mock.assert();
let delete_mock = server.mock(|when, then| {
when.method(POST)
.path("/api/core/background-tasks/del-me/delete/");
then.status(200).json_body(json!({}));
});
let _ = client.core().delete_task("del-me").await;
delete_mock.assert();
}
#[cfg_attr(miri, ignore)]
#[tokio::test]
async fn sync_data_source_uses_expected_path() {
let server = MockServer::start();
let mock = server.mock(|when, then| {
when.method(POST).path("/api/core/data-sources/7/sync/");
then.status(200).json_body(json!({}));
});
let client = mock_client(&server);
let _ = client.core().sync_data_source(7).await;
mock.assert();
}
}