-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for KDL configuration (#42)
This PR adds support for KDL-formatted configuration, in anticipation of supporting more complex load balancing configuration. We'll review whether to switch to KDL as a primary format, revert to only TOML support, or supporting both prior to the 0.3 release.
- Loading branch information
1 parent
ba1d6a8
commit 0c32967
Showing
13 changed files
with
1,141 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[workspace] | ||
resolver = "2" | ||
members = [ | ||
members = [ "experiments/kdl-experiment", | ||
"source/river", | ||
] | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[package] | ||
name = "kdl-experiment" | ||
version = "0.1.0" | ||
edition = "2021" | ||
publish = false | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
kdl = "4.6.0" | ||
miette = { version = "5.10.0", features = ["fancy"] } | ||
pingora = "0.2.0" | ||
thiserror = "1.0.61" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
system { | ||
threads-per-service 8 | ||
} | ||
|
||
services { | ||
Example1 { | ||
listeners { | ||
"0.0.0.0:8080" | ||
"0.0.0.0:4443" cert-path="./assets/test.crt" key-path="./assets/test.key" | ||
"0.0.0.0:8443" cert-path="./assets/test.crt" key-path="./assets/test.key" | ||
} | ||
|
||
connectors { | ||
"91.107.223.4:443" tls-sni="onevariable.com" | ||
} | ||
|
||
path-control { | ||
upstream-request { | ||
filter kind="remove-header-key-regex" pattern=".*SECRET.*" | ||
filter kind="remove-header-key-regex" pattern=".*secret.*" | ||
filter kind="upsert-header" key="x-proxy-friend" value="river" | ||
} | ||
upstream-response { | ||
filter kind="remove-header-key-regex" pattern=".*ETag.*" | ||
filter kind="upsert-header" key="x-with-love-from" value="river" | ||
} | ||
} | ||
} | ||
|
||
Example2 { | ||
listeners { | ||
"0.0.0.0:8000" | ||
} | ||
connectors { | ||
"91.107.223.4:80" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# Test configuration file | ||
# | ||
# This is more in depth than the example. | ||
# | ||
# NOTE: Until we have made a release, configuration format should | ||
# be considered entirely unstable, and likely to make breaking changes | ||
# commit-to-commit! | ||
|
||
[system] | ||
# Threads per service | ||
threads-per-service = 8 | ||
|
||
# Specify a Basic Proxy service, which features minimal configuration. | ||
# | ||
# Note that indentation isn't significant in TOML, it is only done | ||
# here to note the structure of the data. | ||
# | ||
# TODO: This data is very structured, and TOML might not be a good fit. | ||
[[basic-proxy]] | ||
name = "Example1" | ||
|
||
# Each `basic-proxy` can have one or more Listeners, or downstream | ||
# connections. If you provide zero, the basic proxy will terminate | ||
# immediately. | ||
[[basic-proxy.listeners]] | ||
# TODO: "listeners" only has one field, we might want to use | ||
# serde flatten | ||
[basic-proxy.listeners.source] | ||
# Listeners can have kind of "Tcp" (w/ or w/o TLS) or "Uds" | ||
# for "Unix Domain Sockets", which cannot have TLS. | ||
kind = "Tcp" | ||
[basic-proxy.listeners.source.value] | ||
# TCP must specify the address, which includes the port to bind to | ||
addr = "0.0.0.0:8080" | ||
|
||
# `basic-proxy`s can have multiple listeners | ||
[[basic-proxy.listeners]] | ||
|
||
[basic-proxy.listeners.source] | ||
kind = "Tcp" | ||
|
||
[basic-proxy.listeners.source.value] | ||
addr = "0.0.0.0:4443" | ||
|
||
# To enable TLS, specify the path to the certificate and key | ||
[basic-proxy.listeners.source.value.tls] | ||
cert_path = "./assets/test.crt" | ||
key_path = "./assets/test.key" | ||
|
||
# Each `basic proxy` must have exactly one "connector", or the upstream | ||
# server they will proxy to. | ||
# | ||
# To use TLS for upstream connections, specify the SNI of the connection | ||
[basic-proxy.connector] | ||
proxy_addr = "91.107.223.4:443" | ||
tls_sni = "onevariable.com" | ||
|
||
# "Path Control" affects requests and responses as they are proxied | ||
[basic-proxy.path-control] | ||
# upstream request filters specifically allow for the cancellation or modification | ||
# of requests, as they are being made. | ||
# | ||
# Filters are applied in the order they are specified. Multiple instances of | ||
# each filter may be provided. | ||
upstream-request-filters = [ | ||
# Remove any headers with keys matching `pattern` | ||
{ kind = "remove-header-key-regex", pattern = ".*(secret|SECRET).*" }, | ||
# Add or replace (e.g. "Upsert") a fixed header with the given key and value | ||
{ kind = "upsert-header", key = "x-proxy-friend", value = "river" }, | ||
] | ||
|
||
upstream-response-filters = [ | ||
# Remove any headers with keys matching `pattern` | ||
{ kind = "remove-header-key-regex", pattern = ".*ETag.*" }, | ||
# Add or replace (e.g. "Upsert") a fixed header with the given key and value | ||
{ kind = "upsert-header", key = "x-with-love-from", value = "river" }, | ||
] | ||
|
||
# We specify a second basic proxy as well. Here we use the other table syntax | ||
[[basic-proxy]] | ||
name = "Example2" | ||
listeners = [ | ||
{ source = { kind = "Tcp", value = { addr = "0.0.0.0:8000" } } } | ||
] | ||
connector = { proxy_addr = "91.107.223.4:80" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
|
||
use std::{collections::BTreeMap, path::PathBuf}; | ||
|
||
use pingora::{ | ||
server::configuration::{Opt as PingoraOpt, ServerConf as PingoraServerConf}, | ||
upstreams::peer::HttpPeer, | ||
}; | ||
|
||
/// River's internal configuration | ||
#[derive(Debug, Clone)] | ||
pub struct Config { | ||
pub validate_configs: bool, | ||
pub threads_per_service: usize, | ||
pub basic_proxies: Vec<ProxyConfig>, | ||
} | ||
|
||
impl Config { | ||
/// Get the [`Opt`][PingoraOpt] field for Pingora | ||
pub fn pingora_opt(&self) -> PingoraOpt { | ||
// TODO | ||
PingoraOpt { | ||
upgrade: false, | ||
daemon: false, | ||
nocapture: false, | ||
test: self.validate_configs, | ||
conf: None, | ||
} | ||
} | ||
|
||
/// Get the [`ServerConf`][PingoraServerConf] field for Pingora | ||
pub fn pingora_server_conf(&self) -> PingoraServerConf { | ||
PingoraServerConf { | ||
daemon: false, | ||
error_log: None, | ||
// TODO: These are bad assumptions - non-developers will not have "target" | ||
// files, and we shouldn't necessarily use utf-8 strings with fixed separators | ||
// here. | ||
pid_file: String::from("./target/pidfile"), | ||
upgrade_sock: String::from("./target/upgrade"), | ||
user: None, | ||
group: None, | ||
threads: self.threads_per_service, | ||
work_stealing: true, | ||
ca_file: None, | ||
..PingoraServerConf::default() | ||
} | ||
} | ||
|
||
pub fn validate(&self) { | ||
// TODO: validation logic | ||
} | ||
} | ||
|
||
/// Add Path Control Modifiers | ||
/// | ||
/// Note that we use `BTreeMap` and NOT `HashMap`, as we want to maintain the | ||
/// ordering from the configuration file. | ||
#[derive(Default, Debug, Clone)] | ||
pub struct PathControl { | ||
pub(crate) upstream_request_filters: Vec<BTreeMap<String, String>>, | ||
pub(crate) upstream_response_filters: Vec<BTreeMap<String, String>>, | ||
} | ||
|
||
// | ||
// Basic Proxy Configuration | ||
// | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct ProxyConfig { | ||
pub(crate) name: String, | ||
pub(crate) listeners: Vec<ListenerConfig>, | ||
pub(crate) upstream: HttpPeer, | ||
pub(crate) path_control: PathControl, | ||
} | ||
|
||
#[derive(Debug, PartialEq, Clone)] | ||
pub struct TlsConfig { | ||
pub(crate) cert_path: PathBuf, | ||
pub(crate) key_path: PathBuf, | ||
} | ||
|
||
#[derive(Debug, PartialEq, Clone)] | ||
pub struct ListenerConfig { | ||
pub(crate) source: ListenerKind, | ||
} | ||
|
||
#[derive(Debug, PartialEq, Clone)] | ||
pub enum ListenerKind { | ||
Tcp { | ||
addr: String, | ||
tls: Option<TlsConfig>, | ||
}, | ||
Uds(PathBuf), | ||
} | ||
|
||
impl Default for Config { | ||
fn default() -> Self { | ||
Self { | ||
validate_configs: false, | ||
threads_per_service: 8, | ||
basic_proxies: vec![], | ||
} | ||
} | ||
} |
Oops, something went wrong.