use crate::Client;
use crate::error::Result;
use crate::pagination::Page;
use crate::query::QueryBuilder;
use crate::resource::Resource;
pub type IpAddressToInterface = crate::models::IpAddressToInterface;
pub type AvailableIp = crate::models::AvailableIp;
pub type IpAddress = crate::models::IpAddress;
pub type Namespace = crate::models::Namespace;
pub type PrefixLocationAssignment = crate::models::PrefixLocationAssignment;
pub type PrefixLengthRequest = crate::models::PrefixLengthRequest;
pub type Prefix = crate::models::Prefix;
pub type Rir = crate::models::Rir;
pub type RouteTarget = crate::models::RouteTarget;
pub type Service = crate::models::Service;
pub type AvailablePrefix = crate::models::AvailablePrefix;
pub type VlanGroup = crate::models::VlanGroup;
pub type VlanLocationAssignment = crate::models::VlanLocationAssignment;
pub type Vlan = crate::models::Vlan;
pub type VlanAllocationRequest = crate::models::VlanAllocationRequest;
pub type VrfDeviceAssignment = crate::models::VrfDeviceAssignment;
pub type VrfPrefixAssignment = crate::models::VrfPrefixAssignment;
pub type Vrf = crate::models::Vrf;
pub type IpAllocationRequest = crate::models::IpAllocationRequest;
pub type IpAddressToInterfaceApi = Resource<crate::models::IpAddressToInterface>;
pub type IpAddressesApi = Resource<crate::models::IpAddress>;
pub type NamespacesApi = Resource<crate::models::Namespace>;
pub type PrefixLocationAssignmentsApi = Resource<crate::models::PrefixLocationAssignment>;
pub type PrefixesApi = Resource<crate::models::Prefix>;
pub type RirsApi = Resource<crate::models::Rir>;
pub type RouteTargetsApi = Resource<crate::models::RouteTarget>;
pub type ServicesApi = Resource<crate::models::Service>;
pub type VlanGroupsApi = Resource<crate::models::VlanGroup>;
pub type VlanLocationAssignmentsApi = Resource<crate::models::VlanLocationAssignment>;
pub type VlansApi = Resource<crate::models::Vlan>;
pub type VrfDeviceAssignmentsApi = Resource<crate::models::VrfDeviceAssignment>;
pub type VrfPrefixAssignmentsApi = Resource<crate::models::VrfPrefixAssignment>;
pub type VrfsApi = Resource<crate::models::Vrf>;
#[derive(Clone)]
pub struct IpamApi {
client: Client,
}
impl IpamApi {
pub(crate) fn new(client: Client) -> Self {
Self { client }
}
pub fn ip_address_to_interface(&self) -> IpAddressToInterfaceApi {
Resource::new(self.client.clone(), "ipam/ip-address-to-interface/")
}
pub fn ip_addresses(&self) -> IpAddressesApi {
Resource::new(self.client.clone(), "ipam/ip-addresses/")
}
pub fn namespaces(&self) -> NamespacesApi {
Resource::new(self.client.clone(), "ipam/namespaces/")
}
pub fn prefix_location_assignments(&self) -> PrefixLocationAssignmentsApi {
Resource::new(self.client.clone(), "ipam/prefix-location-assignments/")
}
pub async fn prefix_available_ips(
&self,
id: &str,
query: Option<QueryBuilder>,
) -> Result<Page<AvailableIp>> {
let query = query.unwrap_or_default();
self.client
.get_with_params(&format!("ipam/prefixes/{}/available-ips/", id), &query)
.await
}
pub async fn allocate_prefix_ips(
&self,
id: &str,
request: &[IpAllocationRequest],
) -> Result<Page<IpAddress>> {
self.client
.post(&format!("ipam/prefixes/{}/available-ips/", id), request)
.await
}
pub async fn prefix_available_prefixes(
&self,
id: &str,
query: Option<QueryBuilder>,
) -> Result<Page<AvailablePrefix>> {
let query = query.unwrap_or_default();
self.client
.get_with_params(&format!("ipam/prefixes/{}/available-prefixes/", id), &query)
.await
}
pub async fn allocate_prefixes(
&self,
id: &str,
request: &PrefixLengthRequest,
) -> Result<Page<Prefix>> {
self.client
.post(
&format!("ipam/prefixes/{}/available-prefixes/", id),
request,
)
.await
}
pub fn prefixes(&self) -> PrefixesApi {
Resource::new(self.client.clone(), "ipam/prefixes/")
}
pub fn rirs(&self) -> RirsApi {
Resource::new(self.client.clone(), "ipam/rirs/")
}
pub fn route_targets(&self) -> RouteTargetsApi {
Resource::new(self.client.clone(), "ipam/route-targets/")
}
pub fn services(&self) -> ServicesApi {
Resource::new(self.client.clone(), "ipam/services/")
}
pub fn vlan_groups(&self) -> VlanGroupsApi {
Resource::new(self.client.clone(), "ipam/vlan-groups/")
}
pub async fn vlan_group_available_vlans(
&self,
id: &str,
query: Option<QueryBuilder>,
) -> Result<Page<i32>> {
let query = query.unwrap_or_default();
self.client
.get_with_params(&format!("ipam/vlan-groups/{}/available-vlans/", id), &query)
.await
}
pub async fn allocate_vlans(
&self,
id: &str,
request: &[VlanAllocationRequest],
) -> Result<Page<Vlan>> {
self.client
.post(
&format!("ipam/vlan-groups/{}/available-vlans/", id),
request,
)
.await
}
pub fn vlan_location_assignments(&self) -> VlanLocationAssignmentsApi {
Resource::new(self.client.clone(), "ipam/vlan-location-assignments/")
}
pub fn vlans(&self) -> VlansApi {
Resource::new(self.client.clone(), "ipam/vlans/")
}
pub fn vrf_device_assignments(&self) -> VrfDeviceAssignmentsApi {
Resource::new(self.client.clone(), "ipam/vrf-device-assignments/")
}
pub fn vrf_prefix_assignments(&self) -> VrfPrefixAssignmentsApi {
Resource::new(self.client.clone(), "ipam/vrf-prefix-assignments/")
}
pub fn vrfs(&self) -> VrfsApi {
Resource::new(self.client.clone(), "ipam/vrfs/")
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ClientConfig;
use httpmock::{Method::GET, Method::POST, MockServer};
use serde_json::json;
#[cfg_attr(miri, ignore)]
#[tokio::test]
async fn ipam_available_resources_hit_expected_paths() {
let server = MockServer::start();
let config = ClientConfig::new(server.base_url(), "token").with_max_retries(0);
let client = Client::new(config).unwrap();
let api = IpamApi::new(client);
let list_response = json!({
"count": 0,
"next": null,
"previous": null,
"results": []
});
server.mock(|when, then| {
when.method(GET).path("/api/ipam/prefixes/1/available-ips/");
then.status(200).json_body(list_response.clone());
});
server.mock(|when, then| {
when.method(GET)
.path("/api/ipam/prefixes/1/available-prefixes/");
then.status(200).json_body(list_response.clone());
});
server.mock(|when, then| {
when.method(GET)
.path("/api/ipam/vlan-groups/1/available-vlans/");
then.status(200).json_body(list_response.clone());
});
server.mock(|when, then| {
when.method(POST)
.path("/api/ipam/prefixes/1/available-ips/")
.json_body(json!([{"status": {}}]));
then.status(201).json_body(list_response.clone());
});
server.mock(|when, then| {
when.method(POST)
.path("/api/ipam/prefixes/1/available-prefixes/")
.json_body(json!({"prefix_length": 29, "status": {}}));
then.status(201).json_body(list_response.clone());
});
server.mock(|when, then| {
when.method(POST)
.path("/api/ipam/vlan-groups/1/available-vlans/")
.json_body(json!([{"name": "vlan-1", "status": {}}]));
then.status(201).json_body(list_response.clone());
});
let available_ips = api.prefix_available_ips("1", None).await.unwrap();
assert!(available_ips.results.is_empty());
let available_prefixes = api.prefix_available_prefixes("1", None).await.unwrap();
assert!(available_prefixes.results.is_empty());
let available_vlans = api.vlan_group_available_vlans("1", None).await.unwrap();
assert!(available_vlans.results.is_empty());
let status = crate::models::BulkWritableCableRequestStatus::new();
let ip_request = IpAllocationRequest::new(status.clone());
let allocated_ips = api.allocate_prefix_ips("1", &[ip_request]).await.unwrap();
assert!(allocated_ips.results.is_empty());
let prefix_request = PrefixLengthRequest::new(29, status.clone());
let allocated_prefixes = api.allocate_prefixes("1", &prefix_request).await.unwrap();
assert!(allocated_prefixes.results.is_empty());
let vlan_request = VlanAllocationRequest::new("vlan-1".to_string(), status);
let allocated_vlans = api.allocate_vlans("1", &[vlan_request]).await.unwrap();
assert!(allocated_vlans.results.is_empty());
}
}