diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..964be60 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,24 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + branches: + - main + +# Cancel old workflows for PRs (only the most recent workflow can run). +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +# Avoid workflow-level permissions, instead use job-level permissions. +permissions: {} + +jobs: + ubuntu: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: ./ci.sh diff --git a/ci.sh b/ci.sh new file mode 100755 index 0000000..915d949 --- /dev/null +++ b/ci.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -euxo pipefail + +# Format check first +cargo fmt --all -- --check + +# Test all crates +cargo test --all + +# Run configuration file checks +cd ./source/river +cargo run -p river -- --config-toml ./assets/example-config.toml --validate-configs +cargo run -p river -- --config-toml ./assets/test-config.toml --validate-configs +cargo run -p river -- --config-kdl ./assets/test-config.kdl --validate-configs diff --git a/experiments/kdl-experiment/src/config.rs b/experiments/kdl-experiment/src/config.rs index 326ce25..d270254 100644 --- a/experiments/kdl-experiment/src/config.rs +++ b/experiments/kdl-experiment/src/config.rs @@ -1,4 +1,3 @@ - use std::{collections::BTreeMap, path::PathBuf}; use pingora::{ diff --git a/experiments/kdl-experiment/src/main.rs b/experiments/kdl-experiment/src/main.rs index ff6b24e..1ea2bc9 100644 --- a/experiments/kdl-experiment/src/main.rs +++ b/experiments/kdl-experiment/src/main.rs @@ -1,11 +1,6 @@ #![allow(dead_code)] -use std::{ - collections::BTreeMap, - fs::read_to_string, - net::SocketAddr, - path::PathBuf, -}; +use std::{collections::BTreeMap, fs::read_to_string, net::SocketAddr, path::PathBuf}; use config::{Config, ListenerConfig, ListenerKind, PathControl, ProxyConfig, TlsConfig}; use kdl::{KdlDocument, KdlEntry, KdlNode}; diff --git a/source/river/src/config/toml.rs b/source/river/src/config/toml.rs index 17041db..0f52a04 100644 --- a/source/river/src/config/toml.rs +++ b/source/river/src/config/toml.rs @@ -143,8 +143,59 @@ pub enum ListenerKind { Uds(PathBuf), } +impl From for super::internal::ProxyConfig { + fn from(other: ProxyConfig) -> Self { + Self { + name: other.name, + listeners: other.listeners.into_iter().map(Into::into).collect(), + upstream: other.connector.into(), + path_control: other.path_control.into(), + } + } +} + +impl From for super::internal::PathControl { + fn from(value: PathControl) -> Self { + Self { + upstream_request_filters: value.upstream_request_filters, + upstream_response_filters: value.upstream_response_filters, + } + } +} + +impl From for super::internal::TlsConfig { + fn from(other: ListenerTlsConfig) -> Self { + Self { + cert_path: other.cert_path, + key_path: other.key_path, + } + } +} + +impl From for super::internal::ListenerConfig { + fn from(other: ListenerConfig) -> Self { + Self { + source: other.source.into(), + } + } +} + +impl From for super::internal::ListenerKind { + fn from(other: ListenerKind) -> Self { + match other { + ListenerKind::Tcp { addr, tls } => super::internal::ListenerKind::Tcp { + addr, + tls: tls.map(Into::into), + }, + ListenerKind::Uds(a) => super::internal::ListenerKind::Uds(a), + } + } +} + #[cfg(test)] pub mod test { + use std::collections::BTreeMap; + use pingora::upstreams::peer::HttpPeer; use crate::config::{ @@ -206,7 +257,28 @@ pub mod test { tls_sni: Some(String::from("onevariable.com")), }, path_control: crate::config::toml::PathControl { - upstream_request_filters: vec![], + upstream_request_filters: vec![ + BTreeMap::from([ + ("kind".to_string(), "remove-header-key-regex".to_string()), + ("pattern".to_string(), ".*(secret|SECRET).*".to_string()), + ]), + BTreeMap::from([ + ("key".to_string(), "x-proxy-friend".to_string()), + ("kind".to_string(), "upsert-header".to_string()), + ("value".to_string(), "river".to_string()), + ]), + ], + upstream_response_filters: vec![ + BTreeMap::from([ + ("kind".to_string(), "remove-header-key-regex".to_string()), + ("pattern".to_string(), ".*ETag.*".to_string()), + ]), + BTreeMap::from([ + ("key".to_string(), "x-with-love-from".to_string()), + ("kind".to_string(), "upsert-header".to_string()), + ("value".to_string(), "river".to_string()), + ]), + ], }, }, ProxyConfig { @@ -223,6 +295,7 @@ pub mod test { }, path_control: crate::config::toml::PathControl { upstream_request_filters: vec![], + upstream_response_filters: vec![], }, }, ], @@ -259,7 +332,28 @@ pub mod test { String::from("onevariable.com"), ), path_control: internal::PathControl { - upstream_request_filters: vec![], + upstream_request_filters: vec![ + BTreeMap::from([ + ("kind".to_string(), "remove-header-key-regex".to_string()), + ("pattern".to_string(), ".*(secret|SECRET).*".to_string()), + ]), + BTreeMap::from([ + ("key".to_string(), "x-proxy-friend".to_string()), + ("kind".to_string(), "upsert-header".to_string()), + ("value".to_string(), "river".to_string()), + ]), + ], + upstream_response_filters: vec![ + BTreeMap::from([ + ("kind".to_string(), "remove-header-key-regex".to_string()), + ("pattern".to_string(), ".*ETag.*".to_string()), + ]), + BTreeMap::from([ + ("key".to_string(), "x-with-love-from".to_string()), + ("kind".to_string(), "upsert-header".to_string()), + ("value".to_string(), "river".to_string()), + ]), + ], }, }, internal::ProxyConfig { @@ -273,6 +367,7 @@ pub mod test { upstream: HttpPeer::new("91.107.223.4:80", false, String::new()), path_control: internal::PathControl { upstream_request_filters: vec![], + upstream_response_filters: vec![], }, }, ], @@ -287,52 +382,3 @@ pub mod test { assert_eq!(format!("{sys_snapshot:?}"), format!("{cfg:?}")); } } - -impl From for super::internal::ProxyConfig { - fn from(other: ProxyConfig) -> Self { - Self { - name: other.name, - listeners: other.listeners.into_iter().map(Into::into).collect(), - upstream: other.connector.into(), - path_control: other.path_control.into(), - } - } -} - -impl From for super::internal::PathControl { - fn from(value: PathControl) -> Self { - Self { - upstream_request_filters: value.upstream_request_filters, - upstream_response_filters: value.upstream_response_filters, - } - } -} - -impl From for super::internal::TlsConfig { - fn from(other: ListenerTlsConfig) -> Self { - Self { - cert_path: other.cert_path, - key_path: other.key_path, - } - } -} - -impl From for super::internal::ListenerConfig { - fn from(other: ListenerConfig) -> Self { - Self { - source: other.source.into(), - } - } -} - -impl From for super::internal::ListenerKind { - fn from(other: ListenerKind) -> Self { - match other { - ListenerKind::Tcp { addr, tls } => super::internal::ListenerKind::Tcp { - addr, - tls: tls.map(Into::into), - }, - ListenerKind::Uds(a) => super::internal::ListenerKind::Uds(a), - } - } -}