feat(api): add #[non_exhaustive] to public types likely to evolve
ForwardingAction, TargetPattern, ForwardingRule, OperationType, InterfaceConfig, InterfaceKind, DynamicConfig, and CallError are all likely to gain variants/fields in future phases. Marking them #[non_exhaustive] now prevents downstream breakage when new variants/fields are added. Added constructor methods for types that are constructed from other crates.
This commit is contained in:
@@ -2,12 +2,23 @@ use serde::{Deserialize, Serialize};
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct CallError {
|
pub struct CallError {
|
||||||
pub code: String,
|
pub code: String,
|
||||||
pub message: String,
|
pub message: String,
|
||||||
pub retryable: bool,
|
pub retryable: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CallError {
|
||||||
|
pub fn new(code: impl Into<String>, message: impl Into<String>, retryable: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
code: code.into(),
|
||||||
|
message: message.into(),
|
||||||
|
retryable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct ResponseEnvelope {
|
pub struct ResponseEnvelope {
|
||||||
pub request_id: String,
|
pub request_id: String,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub enum OperationType {
|
pub enum OperationType {
|
||||||
Query,
|
Query,
|
||||||
Mutation,
|
Mutation,
|
||||||
|
|||||||
@@ -229,6 +229,7 @@ impl Default for RateLimitConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct DynamicConfig {
|
pub struct DynamicConfig {
|
||||||
pub auth: AuthPolicy,
|
pub auth: AuthPolicy,
|
||||||
pub forwarding: ForwardingPolicy,
|
pub forwarding: ForwardingPolicy,
|
||||||
@@ -244,6 +245,18 @@ impl DynamicConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_parts(
|
||||||
|
auth: AuthPolicy,
|
||||||
|
forwarding: ForwardingPolicy,
|
||||||
|
rate_limits: RateLimitConfig,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
auth,
|
||||||
|
forwarding,
|
||||||
|
rate_limits,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_forwarding_policy(mut self, policy: ForwardingPolicy) -> Self {
|
pub fn with_forwarding_policy(mut self, policy: ForwardingPolicy) -> Self {
|
||||||
self.forwarding = policy;
|
self.forwarding = policy;
|
||||||
self
|
self
|
||||||
|
|||||||
@@ -8,12 +8,14 @@ use crate::auth::identity::Identity;
|
|||||||
use crate::transport::TransportKind;
|
use crate::transport::TransportKind;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub enum ForwardingAction {
|
pub enum ForwardingAction {
|
||||||
Allow,
|
Allow,
|
||||||
Deny,
|
Deny,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub enum TargetPattern {
|
pub enum TargetPattern {
|
||||||
Any,
|
Any,
|
||||||
Host(String),
|
Host(String),
|
||||||
@@ -62,6 +64,7 @@ fn match_cidr(network: &IpNetwork, target: &str) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct ForwardingRule {
|
pub struct ForwardingRule {
|
||||||
pub target: TargetPattern,
|
pub target: TargetPattern,
|
||||||
pub action: ForwardingAction,
|
pub action: ForwardingAction,
|
||||||
@@ -69,6 +72,22 @@ pub struct ForwardingRule {
|
|||||||
pub transports: Vec<TransportKind>,
|
pub transports: Vec<TransportKind>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ForwardingRule {
|
||||||
|
pub fn new(
|
||||||
|
target: TargetPattern,
|
||||||
|
action: ForwardingAction,
|
||||||
|
principals: Vec<String>,
|
||||||
|
transports: Vec<TransportKind>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
target,
|
||||||
|
action,
|
||||||
|
principals,
|
||||||
|
transports,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ForwardingRule {
|
impl ForwardingRule {
|
||||||
fn matches_principal(&self, identity: &Identity) -> bool {
|
fn matches_principal(&self, identity: &Identity) -> bool {
|
||||||
if self.principals.is_empty() {
|
if self.principals.is_empty() {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use crate::auth::IdentityProvider;
|
|||||||
use crate::config::DynamicConfig;
|
use crate::config::DynamicConfig;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[non_exhaustive]
|
||||||
pub enum InterfaceKind {
|
pub enum InterfaceKind {
|
||||||
Ssh,
|
Ssh,
|
||||||
RawFraming,
|
RawFraming,
|
||||||
@@ -21,6 +22,7 @@ impl std::fmt::Display for InterfaceKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[non_exhaustive]
|
||||||
pub enum InterfaceConfig {
|
pub enum InterfaceConfig {
|
||||||
Ssh(SshInterfaceConfig),
|
Ssh(SshInterfaceConfig),
|
||||||
RawFraming(RawFramingConfig),
|
RawFraming(RawFramingConfig),
|
||||||
@@ -28,9 +30,11 @@ pub enum InterfaceConfig {
|
|||||||
|
|
||||||
impl InterfaceConfig {
|
impl InterfaceConfig {
|
||||||
pub fn kind(&self) -> InterfaceKind {
|
pub fn kind(&self) -> InterfaceKind {
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
match self {
|
match self {
|
||||||
InterfaceConfig::Ssh(_) => InterfaceKind::Ssh,
|
InterfaceConfig::Ssh(_) => InterfaceKind::Ssh,
|
||||||
InterfaceConfig::RawFraming(_) => InterfaceKind::RawFraming,
|
InterfaceConfig::RawFraming(_) => InterfaceKind::RawFraming,
|
||||||
|
_ => InterfaceKind::Ssh,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,21 +149,7 @@ fn build_forwarding_policy(config: &ForwardingPolicyConfig) -> napi::Result<Forw
|
|||||||
let target = parse_target_pattern(&rc.target)?;
|
let target = parse_target_pattern(&rc.target)?;
|
||||||
let action = parse_forwarding_action(&rc.action)?;
|
let action = parse_forwarding_action(&rc.action)?;
|
||||||
let principals = rc.principals.clone().unwrap_or_default();
|
let principals = rc.principals.clone().unwrap_or_default();
|
||||||
if principals.is_empty() {
|
rules.push(ForwardingRule::new(target, action, principals, vec![]));
|
||||||
rules.push(ForwardingRule {
|
|
||||||
target,
|
|
||||||
action,
|
|
||||||
principals: vec![],
|
|
||||||
transports: vec![],
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
rules.push(ForwardingRule {
|
|
||||||
target,
|
|
||||||
action,
|
|
||||||
principals,
|
|
||||||
transports: vec![],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(ForwardingPolicy { default, rules })
|
Ok(ForwardingPolicy { default, rules })
|
||||||
@@ -647,11 +633,11 @@ impl AlknetServer {
|
|||||||
pub fn reload_auth(&self, auth: AuthConfigNapi) -> napi::Result<()> {
|
pub fn reload_auth(&self, auth: AuthConfigNapi) -> napi::Result<()> {
|
||||||
let new_auth_policy = build_auth_policy_from_napi(&auth)?;
|
let new_auth_policy = build_auth_policy_from_napi(&auth)?;
|
||||||
let current = self.reload_handle.dynamic();
|
let current = self.reload_handle.dynamic();
|
||||||
let new_config = DynamicConfig {
|
let new_config = DynamicConfig::from_parts(
|
||||||
auth: new_auth_policy,
|
new_auth_policy,
|
||||||
forwarding: current.forwarding.clone(),
|
current.forwarding.clone(),
|
||||||
rate_limits: current.rate_limits.clone(),
|
current.rate_limits.clone(),
|
||||||
};
|
);
|
||||||
self.reload_handle.reload(new_config);
|
self.reload_handle.reload(new_config);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -660,11 +646,11 @@ impl AlknetServer {
|
|||||||
pub fn reload_forwarding(&self, policy: ForwardingPolicyConfig) -> napi::Result<()> {
|
pub fn reload_forwarding(&self, policy: ForwardingPolicyConfig) -> napi::Result<()> {
|
||||||
let new_forwarding = build_forwarding_policy(&policy)?;
|
let new_forwarding = build_forwarding_policy(&policy)?;
|
||||||
let current = self.reload_handle.dynamic();
|
let current = self.reload_handle.dynamic();
|
||||||
let new_config = DynamicConfig {
|
let new_config = DynamicConfig::from_parts(
|
||||||
auth: current.auth.clone(),
|
current.auth.clone(),
|
||||||
forwarding: new_forwarding,
|
new_forwarding,
|
||||||
rate_limits: current.rate_limits.clone(),
|
current.rate_limits.clone(),
|
||||||
};
|
);
|
||||||
self.reload_handle.reload(new_config);
|
self.reload_handle.reload(new_config);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -678,11 +664,11 @@ impl AlknetServer {
|
|||||||
let new_auth_policy = build_auth_policy_from_napi(&auth)?;
|
let new_auth_policy = build_auth_policy_from_napi(&auth)?;
|
||||||
let new_forwarding = build_forwarding_policy(&forwarding)?;
|
let new_forwarding = build_forwarding_policy(&forwarding)?;
|
||||||
let current = self.reload_handle.dynamic();
|
let current = self.reload_handle.dynamic();
|
||||||
let new_config = DynamicConfig {
|
let new_config = DynamicConfig::from_parts(
|
||||||
auth: new_auth_policy,
|
new_auth_policy,
|
||||||
forwarding: new_forwarding,
|
new_forwarding,
|
||||||
rate_limits: current.rate_limits.clone(),
|
current.rate_limits.clone(),
|
||||||
};
|
);
|
||||||
self.reload_handle.reload(new_config);
|
self.reload_handle.reload(new_config);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -755,11 +741,11 @@ pub async fn serve(options: AlknetServeOptions) -> napi::Result<AlknetServer> {
|
|||||||
|
|
||||||
{
|
{
|
||||||
let current = reload_handle.dynamic();
|
let current = reload_handle.dynamic();
|
||||||
let initialized_config = DynamicConfig {
|
let initialized_config = DynamicConfig::from_parts(
|
||||||
auth: initial_auth_policy,
|
initial_auth_policy,
|
||||||
forwarding: current.forwarding.clone(),
|
current.forwarding.clone(),
|
||||||
rate_limits: current.rate_limits.clone(),
|
current.rate_limits.clone(),
|
||||||
};
|
);
|
||||||
drop(current);
|
drop(current);
|
||||||
reload_handle.reload(initialized_config);
|
reload_handle.reload(initialized_config);
|
||||||
}
|
}
|
||||||
@@ -1370,11 +1356,11 @@ mod tests {
|
|||||||
let initial = arc_swap.load();
|
let initial = arc_swap.load();
|
||||||
assert_eq!(initial.forwarding.default, ForwardingAction::Allow);
|
assert_eq!(initial.forwarding.default, ForwardingAction::Allow);
|
||||||
|
|
||||||
let new_config = DynamicConfig {
|
let new_config = DynamicConfig::from_parts(
|
||||||
auth: AuthPolicy::empty(),
|
AuthPolicy::empty(),
|
||||||
forwarding: ForwardingPolicy::deny_all(),
|
ForwardingPolicy::deny_all(),
|
||||||
rate_limits: RateLimitConfig::default(),
|
RateLimitConfig::default(),
|
||||||
};
|
);
|
||||||
handle.reload(new_config);
|
handle.reload(new_config);
|
||||||
|
|
||||||
let updated = arc_swap.load();
|
let updated = arc_swap.load();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
id: cleanup/non-exhaustive-public-api
|
id: cleanup/non-exhaustive-public-api
|
||||||
name: Add #[non_exhaustive] to public API enums and structs likely to evolve
|
name: Add #[non_exhaustive] to public API enums and structs likely to evolve
|
||||||
status: pending
|
status: completed
|
||||||
depends_on:
|
depends_on:
|
||||||
- review/phase1-core-modifications
|
- review/phase1-core-modifications
|
||||||
scope: narrow
|
scope: narrow
|
||||||
@@ -46,4 +46,4 @@ Several public API types introduced in Phase 1 are likely to gain variants or fi
|
|||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
> To be filled on completion
|
> Added #[non_exhaustive] to ForwardingAction, TargetPattern, ForwardingRule, OperationType, InterfaceConfig, InterfaceKind, DynamicConfig, and CallError. Added ForwardingRule::new(), DynamicConfig::from_parts(), and CallError::new() constructors so downstream crates can construct these types. Updated InterfaceConfig::kind() with wildcard arm (allow(unreachable_patterns)). TransportKind was not annotated as it already has tags-only variants and no exhaustive match statements were found.
|
||||||
Reference in New Issue
Block a user