Skip to content

Commit

Permalink
Add documentation, and fix up Match
Browse files Browse the repository at this point in the history
  • Loading branch information
XAMPPRocky committed Feb 4, 2022
1 parent 031f147 commit dde10bf
Show file tree
Hide file tree
Showing 13 changed files with 497 additions and 486 deletions.
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
"proto/quilkin/extensions/filters/firewall/v1alpha1/firewall.proto",
"proto/quilkin/extensions/filters/load_balancer/v1alpha1/load_balancer.proto",
"proto/quilkin/extensions/filters/local_rate_limit/v1alpha1/local_rate_limit.proto",
"proto/quilkin/extensions/filters/matches/v1alpha1/matches.proto",
"proto/quilkin/extensions/filters/match/v1alpha1/match.proto",
"proto/quilkin/extensions/filters/pass/v1alpha1/pass.proto",
"proto/quilkin/extensions/filters/token_router/v1alpha1/token_router.proto",
"proto/udpa/xds/core/v3/resource_name.proto",
Expand Down
7 changes: 5 additions & 2 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@
- [Proxy Configuration](./proxy-configuration.md)
- [Filters](./filters.md)
- [Capture Bytes](./filters/capture_bytes.md)
- [Concatenate Bytes](./filters/concatenate_bytes.md)
- [Compress](./filters/compress.md)
- [Concatenate Bytes](./filters/concatenate_bytes.md)
- [Debug](./filters/debug.md)
- [Drop](./filters/drop.md)
- [Firewall](./filters/firewall.md)
- [Load Balancer](./filters/load_balancer.md)
- [Local Rate Limit](./filters/local_rate_limit.md)
- [Match](./filters/match.md)
- [Pass](./filters/pass.md)
- [Token Router](./filters/token_router.md)
- [Firewall](./filters/firewall.md)
- [Writing Custom Filters](./filters/writing_custom_filters.md)
- [Integrations](./integrations.md)
- [Administration](./admin.md)
Expand Down
20 changes: 20 additions & 0 deletions docs/src/filters/drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Drop

The `Drop` filter always drops any packet passed through it. This is useful in
combination with conditional flow filters like [`Matches`](./match.md)

#### Filter name
```text
quilkin.extensions.filters.drop.v1alpha1.Drop
```

### Configuration Examples
{{#include match.md:example}}

### Configuration

No defined configuration options.

### Metrics

This filter currently exports no metrics.
8 changes: 4 additions & 4 deletions docs/src/filters/matches.md → docs/src/filters/match.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ quilkin.extensions.filters.matches.v1alpha1.Matches
```

### Configuration Examples
<!-- ANCHOR: example -->
```rust
# let yaml = "
version: v1alpha1
Expand All @@ -30,14 +31,13 @@ static:
metadataKey: myapp.com/token
branches:
- value: abc
filter: quilkin.extensions.filters.concatenate_bytes.v1alpha1.ConcatenateBytes
config:
on_read: APPEND
bytes: eHl6 # "xyz"
filter: quilkin.extensions.filters.pass.v1alpha1.Pass
fallthrough: quilkin.extensions.filters.drop.v1alpha1.Drop
# ";
# let config = quilkin::config::Config::from_reader(yaml.as_bytes()).unwrap();
# assert_eq!(config.source.get_static_filters().unwrap().len(), 1);
# quilkin::Builder::from(std::sync::Arc::new(config)).validate().unwrap();
```
<!-- ANCHOR_END: example -->

View the [Matches](../../api/quilkin/filters/matches/struct.Config.html) filter documentation for more details.
20 changes: 20 additions & 0 deletions docs/src/filters/pass.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Pass

The `Pass` filter that always passes any packet through it. This is useful in
combination with conditional flow filters like [`Matches`](./match.md)

#### Filter name
```text
quilkin.extensions.filters.pass.v1alpha1.Pass
```

### Configuration Examples
{{#include match.md:example}}

### Configuration

No defined configuration options.

### Metrics

This filter currently exports no metrics.
2 changes: 0 additions & 2 deletions proto/quilkin/extensions/filters/drop/v1alpha1/drop.proto
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ syntax = "proto3";

package quilkin.extensions.filters.drop.v1alpha1;

import "google/protobuf/wrappers.proto";

message Drop {
}

Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,23 @@ import "google/protobuf/wrappers.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/any.proto";

message Matches {
message Match {
message Branch {
google.protobuf.Value value = 1;
google.protobuf.StringValue filter = 2;
optional google.protobuf.Any config = 3;
Filter filter = 2;
}

message FallthroughFilter {
google.protobuf.StringValue filter = 2;
optional google.protobuf.Any config = 3;
}

message DirectionalConfig {
message Config {
google.protobuf.StringValue metadata_key = 1;
repeated Branch branches = 2;
oneof fallthrough {
google.protobuf.NullValue pass = 3;
google.protobuf.NullValue drop = 4;
FallthroughFilter filter = 5;
}
Filter fallthrough = 4;
}

message Filter {
google.protobuf.StringValue id = 1;
optional google.protobuf.Any config = 2;
}

optional DirectionalConfig on_read = 1;
optional DirectionalConfig on_write = 2;
optional Config on_read = 1;
optional Config on_write = 2;
}
2 changes: 1 addition & 1 deletion src/filters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub mod drop;
pub mod firewall;
pub mod load_balancer;
pub mod local_rate_limit;
pub mod matches;
pub mod r#match;
pub mod metadata;
pub mod pass;
pub mod token_router;
Expand Down
162 changes: 162 additions & 0 deletions src/filters/match.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
mod config;

use crate::{
config::ConfigType,
filters::{prelude::*, registry::FilterRegistry},
metadata::Value,
};

pub use config::Config;

pub const NAME: &str = "quilkin.extensions.filters.matches.v1alpha1.Match";

/// Creates a new factory for generating match filters.
pub fn factory() -> DynFilterFactory {
Box::from(MatchFactory::new())
}

struct ConfigInstance {
metadata_key: String,
branches: Vec<(Value, FilterInstance)>,
fallthrough: FilterInstance,
}

impl ConfigInstance {
fn new(
config: config::DirectionalConfig,
filter_registry: FilterRegistry,
metrics_registry: prometheus::Registry,
) -> Result<Self, Error> {
let map_to_instance = |filter: &str, config_type: Option<ConfigType>| {
let args = CreateFilterArgs::new(
filter_registry.clone(),
metrics_registry.clone(),
config_type,
)
.with_metrics_registry(metrics_registry.clone());

filter_registry.get(filter, args)
};

let branches = config
.branches
.iter()
.map(|branch| {
map_to_instance(&branch.filter.id, branch.filter.config.clone())
.map(|instance| (branch.value.clone(), instance))
})
.collect::<Result<_, _>>()?;

Ok(Self {
metadata_key: config.metadata_key,
branches,
fallthrough: map_to_instance(&config.fallthrough.0.id, config.fallthrough.0.config)?,
})
}
}

struct MatchInstance {
on_read_filters: Option<ConfigInstance>,
on_write_filters: Option<ConfigInstance>,
}

impl MatchInstance {
fn new(
config: Config,
filter_registry: FilterRegistry,
metrics_registry: prometheus::Registry,
) -> Result<Self, Error> {
let on_read_filters = config
.on_read
.map(|config| {
ConfigInstance::new(config, filter_registry.clone(), metrics_registry.clone())
})
.transpose()?;

let on_write_filters = config
.on_write
.map(|config| {
ConfigInstance::new(config, filter_registry.clone(), metrics_registry.clone())
})
.transpose()?;

if on_read_filters.is_none() && on_write_filters.is_none() {
return Err(Error::MissingConfig(NAME));
}

Ok(Self {
on_read_filters,
on_write_filters,
})
}
}

fn match_filter<'config, Ctx, R>(
config: &'config Option<ConfigInstance>,
ctx: Ctx,
get_metadata: impl for<'ctx> Fn(&'ctx Ctx, &'config String) -> Option<&'ctx Value>,
and_then: impl Fn(Ctx, &'config FilterInstance) -> Option<R>,
) -> Option<R>
where
Ctx: Into<R>,
{
match config {
Some(config) => {
let value = (get_metadata)(&ctx, &config.metadata_key)?;

match config.branches.iter().find(|(key, _)| key == value) {
Some((_, instance)) => (and_then)(ctx, instance),
None => (and_then)(ctx, &config.fallthrough),
}
}
None => Some(ctx.into()),
}
}

impl Filter for MatchInstance {
#[cfg_attr(feature = "instrument", tracing::instrument(skip(self, ctx)))]
fn read(&self, ctx: ReadContext) -> Option<ReadResponse> {
match_filter(
&self.on_read_filters,
ctx,
|ctx, metadata_key| ctx.metadata.get(metadata_key),
|ctx, instance| instance.filter.read(ctx),
)
}

#[cfg_attr(feature = "instrument", tracing::instrument(skip(self, ctx)))]
fn write(&self, ctx: WriteContext) -> Option<WriteResponse> {
match_filter(
&self.on_write_filters,
ctx,
|ctx, metadata_key| ctx.metadata.get(metadata_key),
|ctx, instance| instance.filter.write(ctx),
)
}
}

struct MatchFactory;

impl MatchFactory {
pub fn new() -> Self {
Self
}
}

impl FilterFactory for MatchFactory {
fn name(&self) -> &'static str {
NAME
}

fn create_filter(&self, args: CreateFilterArgs) -> Result<FilterInstance, Error> {
let (config_json, config) = self
.require_config(args.config)?
.deserialize::<Config, config::proto::Match>(self.name())?;

let filter = MatchInstance::new(config, args.filter_registry, args.metrics_registry)?;
Ok(FilterInstance::new(
config_json,
Box::new(filter) as Box<dyn Filter>,
))
}
}
Loading

0 comments on commit dde10bf

Please sign in to comment.