pub struct ConfigState {Show 13 fields
pub clusters: BTreeMap<ClusterId, Cluster>,
pub backends: BTreeMap<ClusterId, Vec<Backend>>,
pub http_listeners: BTreeMap<ListenerKey, HttpListenerConfig>,
pub https_listeners: BTreeMap<ListenerKey, HttpsListenerConfig>,
pub tcp_listeners: BTreeMap<ListenerKey, TcpListenerConfig>,
pub udp_listeners: BTreeMap<ListenerKey, UdpListenerConfig>,
pub http_fronts: BTreeMap<String, HttpFrontend>,
pub https_fronts: BTreeMap<String, HttpFrontend>,
pub tcp_fronts: HashMap<ClusterId, Vec<TcpFrontend>>,
pub udp_fronts: HashMap<ClusterId, Vec<UdpFrontend>>,
pub certificates: HashMap<SocketAddr, HashMap<Fingerprint, CertificateAndKey>>,
pub certificate_metadata: HashMap<SocketAddr, CertificateMetadataIndex>,
pub request_counts: BTreeMap<String, i32>,
}Expand description
The ConfigState represents the state of Sōzu’s business, which is to forward traffic
from frontends to backends. Hence, it contains all details about:
- listeners (socket addresses, for TCP and HTTP connections)
- frontends (bind to a listener)
- backends (to forward connections to)
- clusters (routing rules from frontends to backends)
- TLS certificates
Fields§
§clusters: BTreeMap<ClusterId, Cluster>§backends: BTreeMap<ClusterId, Vec<Backend>>§http_listeners: BTreeMap<ListenerKey, HttpListenerConfig>listener key (address, plus interface when bound) -> HTTP listener
https_listeners: BTreeMap<ListenerKey, HttpsListenerConfig>listener key -> HTTPS listener
tcp_listeners: BTreeMap<ListenerKey, TcpListenerConfig>listener key -> TCP listener
udp_listeners: BTreeMap<ListenerKey, UdpListenerConfig>listener key -> UDP listener
http_fronts: BTreeMap<String, HttpFrontend>HTTP frontends, indexed by a summary of each front’s address;hostname;path, for uniqueness.
For example: "0.0.0.0:8080;lolcatho.st;P/api"
https_fronts: BTreeMap<String, HttpFrontend>indexed by (address, hostname, path)
tcp_fronts: HashMap<ClusterId, Vec<TcpFrontend>>§udp_fronts: HashMap<ClusterId, Vec<UdpFrontend>>§certificates: HashMap<SocketAddr, HashMap<Fingerprint, CertificateAndKey>>TLS certificate material by listener address and leaf fingerprint.
Mutations must go through Self::dispatch so
Self::certificate_metadata remains coherent. The map stays public
for compatibility, but replacing entries directly in memory can
invalidate the sidecar without changing either map’s cardinality; that
shape cannot be detected by the O(1) mutation fast path. Deserialized
state is treated as untrusted and normalized on its first successful
certificate mutation.
certificate_metadata: HashMap<SocketAddr, CertificateMetadataIndex>Selection metadata for entries in certificates, keyed identically.
A missing or partial sidecar is a valid legacy state. Read paths derive a deterministic total order and certificate mutations normalize the affected address only after all fallible validation has succeeded.
request_counts: BTreeMap<String, i32>A census of requests that were received. Name of the request -> number of occurences
Implementations§
Source§impl ConfigState
impl ConfigState
pub fn new() -> Self
Sourcepub fn ordered_certificate_entries(
&self,
address: SocketAddr,
) -> Vec<(Fingerprint, &CertificateAndKey, CertificateMetadata)>
pub fn ordered_certificate_entries( &self, address: SocketAddr, ) -> Vec<(Fingerprint, &CertificateAndKey, CertificateMetadata)>
Certificates at address in their effective runtime insertion order.
Legacy or externally deserialized states may have missing, duplicate or
gapped ordinals. They remain readable: entries without metadata sort
first by fingerprint; metadata-bearing entries follow by ordinal and
then fingerprint. The returned ordinals are always normalized to the
contiguous range 0..len, without mutating self.
Sourcepub fn certificate_add_requests_for_address(
&self,
address: SocketAddr,
) -> Vec<AddCertificate>
pub fn certificate_add_requests_for_address( &self, address: SocketAddr, ) -> Vec<AddCertificate>
Replay requests for one listener, ordered exactly as its resolver was populated and carrying every retained expiration override.
Sourcepub fn rollback_for(&self, request: &RequestType) -> Option<Request>
pub fn rollback_for(&self, request: &RequestType) -> Option<Request>
Capture the compensating request that restores this exact state if
request is accepted here but refused by the runtime afterwards.
Additions whose inverse is independent of prior state use
rollback_request. Frontend removals instead snapshot the stored
frontend before dispatch: their wire request is only a selector and
can omit metadata that an Add must restore. Listener activation also
snapshots the stored active flag so a refused activation only undoes
the transition from inactive to active.
pub fn dispatch(&mut self, request: &Request) -> Result<(), StateError>
pub fn get_request_counts(&self) -> RequestCounts
Sourcepub fn cluster_removal_requests(&self, cluster_id: &str) -> Vec<Request>
pub fn cluster_removal_requests(&self, cluster_id: &str) -> Vec<Request>
The removal orders for every frontend and backend
ConfigState::remove_cluster would remove with cluster_id, or none when
the state does not hold that cluster. A worker reads them from its own
state before applying a RemoveCluster to it, then applies them to
its proxies so they drop what the state drops.
Sourcepub fn removed_with_its_cluster(
&self,
request: &Request,
error: &StateError,
) -> bool
pub fn removed_with_its_cluster( &self, request: &Request, error: &StateError, ) -> bool
Whether error, the answer Self::dispatch gave to request,
means the frontend or backend request removes already went away
with its cluster: the removal found nothing to remove (NotFound),
and the state does not hold the cluster it names either, so
RemoveCluster removed it. Such a removal has nothing left to do and
is answered ok, which keeps sozu cluster remove followed by the
removal of each of its frontends working. A frontend without a
cluster_id names no cluster and never matches.
It never covers an object another cluster owns: a frontend removal
matches only a frontend of the cluster it names (see
remove_frontend_from), so its NotFound leaves such an object alone.
Sourcepub fn removed_with_its_cluster_message(&self, request: &Request) -> String
pub fn removed_with_its_cluster_message(&self, request: &Request) -> String
The answer to a removal Self::removed_with_its_cluster accepts.
The same answer covers a cluster that never existed, a typo for
instance, so it says the cluster does not exist and, when another
cluster (or a route with no cluster) now holds the same key or
address, which one: that object is not removed.
pub fn list_health_checks(&self, cluster_id: Option<&str>) -> HealthChecksList
Sourcepub fn client_auth_refresh(
&self,
listener: &HttpsListenerConfig,
) -> Option<UpdateHttpsListenerConfig>
pub fn client_auth_refresh( &self, listener: &HttpsListenerConfig, ) -> Option<UpdateHttpsListenerConfig>
The patch a configuration reload sends for an HTTPS listener that is already running with another client authentication policy.
A reload replays AddHttpsListener for every listener of the file,
and the state refuses it for an address it already holds, so a CA or
CRL refreshed on disk would never reach the workers. With revocation
expiry enforced, a CRL that could not be refreshed would end up
rejecting every client. None when no listener is at that key, or
when its policy already matches.
Sourcepub fn health_check_port_unix_conflict(
&self,
request: &RequestType,
) -> Option<&'static str>
pub fn health_check_port_unix_conflict( &self, request: &RequestType, ) -> Option<&'static str>
Why request would put a health check port next to a backend with a
unix_path in one cluster, which
sozu_command::config::HEALTH_CHECK_PORT_UNIX_REFUSED forbids, in either order of arrival: the port set on a cluster that
holds a unix backend (AddCluster, SetHealthCheck), or a unix backend
added to a cluster whose health check sets a port.
None for every other request, and for one a more specific refusal
already covers (an unknown cluster, an invalid health check, a UDP
cluster, a unix_path that does not parse), so those diagnostics keep
their precedence. The worker asks this before dispatching, because it
must not touch its proxies for a request the state refuses.
pub fn generate_activate_requests(&self) -> Vec<Request>
pub fn diff(&self, other: &ConfigState) -> Vec<Request>
pub fn hash_state(&self) -> BTreeMap<ClusterId, u64>
Sourcepub fn cluster_state(&self, cluster_id: &str) -> Option<ClusterInformation>
pub fn cluster_state(&self, cluster_id: &str) -> Option<ClusterInformation>
Gives details about a given cluster.
Types like HttpFrontend are converted into protobuf ones, like RequestHttpFrontend
pub fn count_backends(&self) -> usize
pub fn count_frontends(&self) -> usize
pub fn get_cluster_ids_by_domain( &self, hostname: String, path: Option<String>, ) -> HashSet<ClusterId>
Sourcepub fn get_certificates(
&self,
filters: QueryCertificatesFilters,
) -> BTreeMap<String, CertificateAndKey>
pub fn get_certificates( &self, filters: QueryCertificatesFilters, ) -> BTreeMap<String, CertificateAndKey>
Filter the control plane’s certificate record.
filters.domain is matched by exact SAN equality and is tested
before filters.fingerprint, so a request carrying both answers the
domain only. That is deliberately NOT the question
sozu certificate list --domain <host> asks: the certificate that
serves a handshake is chosen by CertificateResolver::domain_lookup,
a TrieNode lookup resolving *. wildcard and regex labels, so a
*.example.com certificate is invisible to an exact-equality query
for foo.example.com (sozu#1383).
The trie lives in sozu-lib, which depends on this crate — the
reverse edge is a cargo cycle — so the operator-facing --domain
query is resolved one layer up, in bin’s
certificates_serving_domain (bin/src/command/requests.rs). Do not
reimplement hostname matching here: a second implementation is what
drifts from the resolver and reopens sozu#1383.
pub fn list_frontends(&self, filters: FrontendFilters) -> ListedFrontends
pub fn list_listeners(&self) -> ListenersList
pub fn produce_initial_state(&self) -> InitialState
Sourcepub fn write_initial_state_to_file(
&self,
file: &mut File,
) -> Result<usize, StateError>
pub fn write_initial_state_to_file( &self, file: &mut File, ) -> Result<usize, StateError>
generate requests necessary to recreate the state, in protobuf, to a temp file
Sourcepub fn write_requests_to_file(
&self,
file: &mut File,
) -> Result<usize, StateError>
pub fn write_requests_to_file( &self, file: &mut File, ) -> Result<usize, StateError>
generate requests necessary to recreate the state, write them in a JSON form in a file, separated by \n\0, returns the number of written requests
Trait Implementations§
Source§impl Clone for ConfigState
impl Clone for ConfigState
Source§impl Debug for ConfigState
impl Debug for ConfigState
Source§impl Default for ConfigState
impl Default for ConfigState
Source§impl<'de> Deserialize<'de> for ConfigState
impl<'de> Deserialize<'de> for ConfigState
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for ConfigState
Source§impl PartialEq for ConfigState
impl PartialEq for ConfigState
Source§impl Serialize for ConfigState
impl Serialize for ConfigState
impl StructuralPartialEq for ConfigState
Auto Trait Implementations§
impl Freeze for ConfigState
impl RefUnwindSafe for ConfigState
impl Send for ConfigState
impl Sync for ConfigState
impl Unpin for ConfigState
impl UnsafeUnpin for ConfigState
impl UnwindSafe for ConfigState
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> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.