pub struct OverlayManager { /* private fields */ }Expand description
Manages overlay networks for a deployment
Implementations§
Source§impl OverlayManager
impl OverlayManager
Sourcepub async fn new(deployment: String) -> Result<Self, AgentError>
pub async fn new(deployment: String) -> Result<Self, AgentError>
Create a new overlay manager for a deployment (legacy single-node path).
This constructor hands out container IPs from the full default cluster
/16 (10.200.0.0/16). In multi-node deployments every node’s agent
would then independently allocate from the same flat range, producing
IP collisions. Prefer OverlayManager::with_slice for cluster
deployments so the agent is bounded to a per-node slice assigned by
the leader’s NodeSliceAllocator.
§Errors
Returns an error if the overlay manager cannot be initialized.
§Panics
Panics if the default CIDR 10.200.0.0/16 cannot be parsed (this is a compile-time constant).
Sourcepub fn with_slice(
deployment: String,
cluster_cidr: IpNetwork,
slice_cidr: IpNetwork,
port: u16,
) -> Self
pub fn with_slice( deployment: String, cluster_cidr: IpNetwork, slice_cidr: IpNetwork, port: u16, ) -> Self
Create an OverlayManager bound to a per-node slice.
slice_cidr is a /28 (or whatever the cluster’s slice prefix is)
owned by this node, assigned by the leader’s NodeSliceAllocator. The
internal IpAllocator is bounded to this slice so container IPs never
collide across nodes.
cluster_cidr is the full cluster CIDR (e.g. 10.200.0.0/16), kept
for configuration / logging purposes. The allocator itself only uses
slice_cidr.
Sourcepub fn with_overlay_port(self, port: u16) -> Self
pub fn with_overlay_port(self, port: u16) -> Self
Set the WireGuard listen port for the overlay network.
Sourcepub fn with_nat_config(self, nat: NatConfig) -> Self
pub fn with_nat_config(self, nat: NatConfig) -> Self
Set the NAT traversal configuration for the overlay network.
When set, the NatConfig is threaded into every OverlayConfig
the manager builds (global and per-service). When unset (the default),
OverlayConfig::default() is used, which itself defaults to
NatConfig::default() — i.e. NAT traversal enabled with public STUN.
Sourcepub async fn service_count(&self) -> usize
pub async fn service_count(&self) -> usize
Returns the number of services currently registered with this manager.
Counts entries in service_interfaces, which is populated by
OverlayManager::setup_service_overlay regardless of whether the
underlying overlay transport was successfully created or fell through
to direct networking. Useful for the race regression test in
tests/overlay_setup_race.rs and for telemetry endpoints.
Sourcepub fn nat_enabled(&self) -> bool
pub fn nat_enabled(&self) -> bool
Returns whether NAT traversal is enabled for this manager.
Reflects the most recent with_nat_config() call. When no NAT config
has been provided this falls back to NatConfig::default which has
enabled = true.
Sourcepub fn nat_config(&self) -> Option<NatConfig>
pub fn nat_config(&self) -> Option<NatConfig>
Returns a clone of the configured NatConfig, or None if no
override was provided. Used by the API layer to surface the daemon’s
effective NAT configuration without exposing the raw
NatConfig::default() baseline.
Sourcepub async fn start_nat_traversal(&self) -> Result<bool, AgentError>
pub async fn start_nat_traversal(&self) -> Result<bool, AgentError>
Bootstrap a NatTraversal orchestrator for this manager.
Constructs a fresh NatTraversal from the configured NatConfig
(defaulting when none is set), gathers ICE-style local candidates
(host + STUN reflexive + relay) and stores it for later
OverlayManager::nat_maintenance_tick / status calls.
No-op when enabled = false in the configured NatConfig. Failures
during candidate gathering are logged and surfaced as Ok(false) so
the caller can decide whether to spawn a maintenance loop or skip it.
Returns Ok(true) when the traversal was successfully constructed and
at least one candidate was gathered, Ok(false) when NAT is disabled
or candidate gathering yielded nothing actionable.
§Errors
Returns an error only on unexpected internal failures; STUN/TURN
network errors are downgraded to Ok(false) with a warning log so
the daemon can boot with NAT degraded rather than aborting.
Sourcepub async fn nat_maintenance_tick(&self) -> Result<(), AgentError>
pub async fn nat_maintenance_tick(&self) -> Result<(), AgentError>
Periodic NAT traversal maintenance: re-probe STUN, refresh relays, attempt to upgrade relayed peer connections to direct/hole-punched.
Intended to be called from a tokio::time::interval loop spawned by
the daemon. No-op when OverlayManager::start_nat_traversal has
not yet succeeded.
§Errors
Returns an error when the underlying STUN refresh fails. The daemon’s loop logs and ignores these so a transient STUN outage doesn’t kill the maintenance task.
Sourcepub async fn nat_status_snapshot(&self) -> NatStatusSnapshot
pub async fn nat_status_snapshot(&self) -> NatStatusSnapshot
Snapshot the current NAT traversal state for API consumers.
Returns an empty snapshot when NAT traversal has not been started.
Per-peer entries are not yet tracked here (the agent path does not
route peers through NatTraversal::connect_to_peer); callers should
treat the peers list as advisory.
Sourcepub fn set_dns_config(
&mut self,
addr: Option<SocketAddr>,
domain: Option<String>,
)
pub fn set_dns_config( &mut self, addr: Option<SocketAddr>, domain: Option<String>, )
Record the overlay DNS server address and zone domain so attaches can
propagate them to HCN endpoint schemas (Windows) and future
per-container DNS plumbing (Linux /etc/resolv.conf).
addr is the socket address the overlay hickory DNS server is
listening on (typically overlay_ip:15353). domain is the DNS zone
(e.g. "overlay.local"). Either may be omitted independently.
Sourcepub fn with_dns_config(
self,
addr: Option<SocketAddr>,
domain: Option<String>,
) -> Self
pub fn with_dns_config( self, addr: Option<SocketAddr>, domain: Option<String>, ) -> Self
Builder-style variant of OverlayManager::set_dns_config.
Sourcepub fn dns_server_addr(&self) -> Option<SocketAddr>
pub fn dns_server_addr(&self) -> Option<SocketAddr>
Returns the overlay DNS server address if the daemon bootstrapped one.
Sourcepub fn dns_domain(&self) -> Option<&str>
pub fn dns_domain(&self) -> Option<&str>
Returns the overlay DNS zone domain, if configured.
Sourcepub async fn setup_global_overlay(&mut self) -> Result<(), AgentError>
pub async fn setup_global_overlay(&mut self) -> Result<(), AgentError>
Setup the global overlay network for the deployment
§Errors
Returns an error if key generation or interface creation fails.
Sourcepub async fn setup_service_overlay(
&self,
service_name: &str,
) -> Result<String, AgentError>
pub async fn setup_service_overlay( &self, service_name: &str, ) -> Result<String, AgentError>
Setup a service-scoped overlay network
§Errors
Returns an error if the overlay interface cannot be created.
Sourcepub async fn attach_container(
&self,
container_pid: u32,
service_name: &str,
join_global: bool,
) -> Result<IpAddr, AgentError>
pub async fn attach_container( &self, container_pid: u32, service_name: &str, join_global: bool, ) -> Result<IpAddr, AgentError>
Add a container to the appropriate overlay networks.
On non-Linux platforms this is a no-op: per-container overlay attachment
relies on Linux network namespaces (veth pairs + nsenter). On macOS,
containers share the host network, so the node’s overlay IP is returned
directly and the proxy differentiates traffic by port.
§Errors
Returns an error if the container cannot be attached to the overlay network.
Sourcepub async fn teardown_service_overlay(&self, service_name: &str)
pub async fn teardown_service_overlay(&self, service_name: &str)
Tear down the overlay network for a single service.
Removes the service’s TUN transport (destroying the interface) and clears its entry from the interface tracking map. This is safe to call even if no overlay was created for the service (it will be a no-op).
Sourcepub async fn cleanup(&mut self) -> Result<(), AgentError>
pub async fn cleanup(&mut self) -> Result<(), AgentError>
Sourcepub fn node_ip(&self) -> Option<IpAddr>
pub fn node_ip(&self) -> Option<IpAddr>
Returns this node’s IP on the global overlay network, if available.
This is set after [setup_global_overlay] completes successfully.
Sourcepub fn deployment(&self) -> &str
pub fn deployment(&self) -> &str
Returns the deployment name this overlay manager was created for.
Sourcepub fn global_interface(&self) -> Option<&str>
pub fn global_interface(&self) -> Option<&str>
Returns the global overlay interface name, if one has been created.
Sourcepub fn overlay_port(&self) -> u16
pub fn overlay_port(&self) -> u16
Returns the WireGuard listen port for the overlay network.
Sourcepub fn has_global_transport(&self) -> bool
pub fn has_global_transport(&self) -> bool
Returns true if the global overlay transport is active.
Sourcepub async fn service_transport_count(&self) -> usize
pub async fn service_transport_count(&self) -> usize
Returns the number of service-specific overlay transports currently active.
Sourcepub fn overlay_cidr(&self) -> String
pub fn overlay_cidr(&self) -> String
Returns the CIDR string for the overlay IP allocator.
Sourcepub fn slice_cidr(&self) -> Option<IpNetwork>
pub fn slice_cidr(&self) -> Option<IpNetwork>
Returns the per-node slice CIDR this manager was built with, or None
if the legacy OverlayManager::new constructor was used.
Sourcepub fn cluster_cidr(&self) -> Option<IpNetwork>
pub fn cluster_cidr(&self) -> Option<IpNetwork>
Returns the full cluster CIDR, if this manager was constructed with
one. The legacy OverlayManager::new path stores the default
10.200.0.0/16.
Sourcepub async fn persist_ipam_state(&self, path: &Path) -> Result<(), AgentError>
pub async fn persist_ipam_state(&self, path: &Path) -> Result<(), AgentError>
Persist the IPAM allocator state to path.
The state is a small JSON blob capturing the allocator’s CIDR bound and its next-offset counter so restarts don’t re-hand-out the same IPs.
§Errors
Returns an error if the file cannot be written.
Sourcepub async fn restore_ipam_state(
&mut self,
path: &Path,
) -> Result<(), AgentError>
pub async fn restore_ipam_state( &mut self, path: &Path, ) -> Result<(), AgentError>
Restore IPAM allocator state from path.
If the file does not exist this is a no-op (the allocator keeps its current counter). On load mismatch (e.g. the persisted CIDR differs from the allocator’s current CIDR) the counter is left untouched and a warning is emitted.
§Errors
Returns an error if the file exists but cannot be read or parsed.
Sourcepub fn ip_alloc_stats(&self) -> (u64, IpAddr)
pub fn ip_alloc_stats(&self) -> (u64, IpAddr)
Returns IP allocation statistics: (allocated_count, next_offset).
Auto Trait Implementations§
impl !Freeze for OverlayManager
impl !RefUnwindSafe for OverlayManager
impl Send for OverlayManager
impl Sync for OverlayManager
impl Unpin for OverlayManager
impl UnsafeUnpin for OverlayManager
impl !UnwindSafe for OverlayManager
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
Source§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::RequestSource§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> ServiceExt for T
impl<T> ServiceExt for T
Source§fn propagate_header(self, header: HeaderName) -> PropagateHeader<Self>where
Self: Sized,
fn propagate_header(self, header: HeaderName) -> PropagateHeader<Self>where
Self: Sized,
Source§fn add_extension<T>(self, value: T) -> AddExtension<Self, T>where
Self: Sized,
fn add_extension<T>(self, value: T) -> AddExtension<Self, T>where
Self: Sized,
Source§fn map_request_body<F>(self, f: F) -> MapRequestBody<Self, F>where
Self: Sized,
fn map_request_body<F>(self, f: F) -> MapRequestBody<Self, F>where
Self: Sized,
Source§fn map_response_body<F>(self, f: F) -> MapResponseBody<Self, F>where
Self: Sized,
fn map_response_body<F>(self, f: F) -> MapResponseBody<Self, F>where
Self: Sized,
Source§fn compression(self) -> Compression<Self>where
Self: Sized,
fn compression(self) -> Compression<Self>where
Self: Sized,
Source§fn decompression(self) -> Decompression<Self>where
Self: Sized,
fn decompression(self) -> Decompression<Self>where
Self: Sized,
Source§fn trace_for_http(self) -> Trace<Self, SharedClassifier<ServerErrorsAsFailures>>where
Self: Sized,
fn trace_for_http(self) -> Trace<Self, SharedClassifier<ServerErrorsAsFailures>>where
Self: Sized,
Source§fn trace_for_grpc(self) -> Trace<Self, SharedClassifier<GrpcErrorsAsFailures>>where
Self: Sized,
fn trace_for_grpc(self) -> Trace<Self, SharedClassifier<GrpcErrorsAsFailures>>where
Self: Sized,
Source§fn follow_redirects(self) -> FollowRedirect<Self>where
Self: Sized,
fn follow_redirects(self) -> FollowRedirect<Self>where
Self: Sized,
Source§fn sensitive_headers(
self,
headers: impl IntoIterator<Item = HeaderName>,
) -> SetSensitiveRequestHeaders<SetSensitiveResponseHeaders<Self>>where
Self: Sized,
fn sensitive_headers(
self,
headers: impl IntoIterator<Item = HeaderName>,
) -> SetSensitiveRequestHeaders<SetSensitiveResponseHeaders<Self>>where
Self: Sized,
Source§fn sensitive_request_headers(
self,
headers: impl IntoIterator<Item = HeaderName>,
) -> SetSensitiveRequestHeaders<Self>where
Self: Sized,
fn sensitive_request_headers(
self,
headers: impl IntoIterator<Item = HeaderName>,
) -> SetSensitiveRequestHeaders<Self>where
Self: Sized,
Source§fn sensitive_response_headers(
self,
headers: impl IntoIterator<Item = HeaderName>,
) -> SetSensitiveResponseHeaders<Self>where
Self: Sized,
fn sensitive_response_headers(
self,
headers: impl IntoIterator<Item = HeaderName>,
) -> SetSensitiveResponseHeaders<Self>where
Self: Sized,
Source§fn override_request_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetRequestHeader<Self, M>where
Self: Sized,
fn override_request_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetRequestHeader<Self, M>where
Self: Sized,
Source§fn append_request_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetRequestHeader<Self, M>where
Self: Sized,
fn append_request_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetRequestHeader<Self, M>where
Self: Sized,
Source§fn insert_request_header_if_not_present<M>(
self,
header_name: HeaderName,
make: M,
) -> SetRequestHeader<Self, M>where
Self: Sized,
fn insert_request_header_if_not_present<M>(
self,
header_name: HeaderName,
make: M,
) -> SetRequestHeader<Self, M>where
Self: Sized,
Source§fn override_response_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetResponseHeader<Self, M>where
Self: Sized,
fn override_response_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetResponseHeader<Self, M>where
Self: Sized,
Source§fn append_response_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetResponseHeader<Self, M>where
Self: Sized,
fn append_response_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetResponseHeader<Self, M>where
Self: Sized,
Source§fn insert_response_header_if_not_present<M>(
self,
header_name: HeaderName,
make: M,
) -> SetResponseHeader<Self, M>where
Self: Sized,
fn insert_response_header_if_not_present<M>(
self,
header_name: HeaderName,
make: M,
) -> SetResponseHeader<Self, M>where
Self: Sized,
Source§fn set_request_id<M>(
self,
header_name: HeaderName,
make_request_id: M,
) -> SetRequestId<Self, M>where
Self: Sized,
M: MakeRequestId,
fn set_request_id<M>(
self,
header_name: HeaderName,
make_request_id: M,
) -> SetRequestId<Self, M>where
Self: Sized,
M: MakeRequestId,
Source§fn set_x_request_id<M>(self, make_request_id: M) -> SetRequestId<Self, M>where
Self: Sized,
M: MakeRequestId,
fn set_x_request_id<M>(self, make_request_id: M) -> SetRequestId<Self, M>where
Self: Sized,
M: MakeRequestId,
x-request-id as the header name. Read moreSource§fn propagate_request_id(
self,
header_name: HeaderName,
) -> PropagateRequestId<Self>where
Self: Sized,
fn propagate_request_id(
self,
header_name: HeaderName,
) -> PropagateRequestId<Self>where
Self: Sized,
Source§fn propagate_x_request_id(self) -> PropagateRequestId<Self>where
Self: Sized,
fn propagate_x_request_id(self) -> PropagateRequestId<Self>where
Self: Sized,
x-request-id as the header name. Read moreSource§fn catch_panic(self) -> CatchPanic<Self, DefaultResponseForPanic>where
Self: Sized,
fn catch_panic(self) -> CatchPanic<Self, DefaultResponseForPanic>where
Self: Sized,
500 Internal Server responses. Read moreSource§fn request_body_limit(self, limit: usize) -> RequestBodyLimit<Self>where
Self: Sized,
fn request_body_limit(self, limit: usize) -> RequestBodyLimit<Self>where
Self: Sized,
413 Payload Too Large responses. Read more