From 1fce3a8d15a8faf6063188bb0bafdf275a5c0b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Fournier?= Date: Wed, 1 Feb 2023 14:07:03 +0100 Subject: [PATCH 1/6] feat: implement simplify tokens --- Cargo.lock | 247 +++++++++++++++++++++- server/Cargo.toml | 5 + server/benches/benchmark.rs | 37 ++++ server/src/data_sources/mod.rs | 2 +- server/src/data_sources/redis_provider.rs | 4 +- server/src/error.rs | 7 +- server/src/frontend_api.rs | 2 +- server/src/lib.rs | 2 + server/src/main.rs | 1 - server/src/tls.rs | 2 +- server/src/tokens.rs | 99 +++++++++ server/src/types.rs | 93 +++++++- server/tests/redis_test.rs | 3 +- 13 files changed, 488 insertions(+), 16 deletions(-) create mode 100644 server/benches/benchmark.rs create mode 100644 server/src/tokens.rs diff --git a/Cargo.lock b/Cargo.lock index 30ed2f43..89379ba1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -297,6 +297,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + [[package]] name = "ansi_term" version = "0.12.1" @@ -426,6 +432,12 @@ dependencies = [ "bytes", ] +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cc" version = "1.0.78" @@ -457,6 +469,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "ciborium" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" + +[[package]] +name = "ciborium-ll" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "clap" version = "2.34.0" @@ -467,11 +506,23 @@ dependencies = [ "atty", "bitflags", "strsim 0.8.0", - "textwrap", + "textwrap 0.11.0", "unicode-width", "vec_map", ] +[[package]] +name = "clap" +version = "3.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +dependencies = [ + "bitflags", + "clap_lex 0.2.4", + "indexmap", + "textwrap 0.16.0", +] + [[package]] name = "clap" version = "4.1.4" @@ -480,7 +531,7 @@ checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76" dependencies = [ "bitflags", "clap_derive", - "clap_lex", + "clap_lex 0.3.1", "is-terminal", "once_cell", "strsim 0.10.0", @@ -500,6 +551,15 @@ dependencies = [ "syn", ] +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "clap_lex" version = "0.3.1" @@ -605,6 +665,42 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "criterion" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" +dependencies = [ + "anes", + "atty", + "cast", + "ciborium", + "clap 3.2.23", + "criterion-plot", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools", +] + [[package]] name = "crossbeam-channel" version = "0.5.6" @@ -615,6 +711,30 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + [[package]] name = "crossbeam-utils" version = "0.8.14" @@ -825,6 +945,12 @@ dependencies = [ "clap 2.34.0", ] +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + [[package]] name = "encoding_rs" version = "0.8.31" @@ -1035,6 +1161,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + [[package]] name = "hashbrown" version = "0.12.3" @@ -1194,6 +1326,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06d198e9919d9822d5f7083ba8530e04de87841eaf21ead9af8f2304efd57c89" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.5" @@ -1327,6 +1468,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.16" @@ -1414,6 +1564,12 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + [[package]] name = "opentelemetry" version = "0.18.0" @@ -1591,6 +1747,34 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +[[package]] +name = "plotters" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" + +[[package]] +name = "plotters-svg" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" +dependencies = [ + "plotters-backend", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1705,6 +1889,28 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "redis" version = "0.22.3" @@ -1819,6 +2025,15 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -2088,6 +2303,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + [[package]] name = "thiserror" version = "1.0.38" @@ -2157,6 +2378,16 @@ dependencies = [ "time-core", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -2412,6 +2643,7 @@ dependencies = [ "anyhow", "chrono", "clap 4.1.4", + "criterion", "dotenv", "env_logger", "opentelemetry", @@ -2533,6 +2765,17 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" diff --git a/server/Cargo.toml b/server/Cargo.toml index 94862dbf..fd57f388 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -36,9 +36,14 @@ unleash-types = { version = "0.7.0", features = ["openapi", "hashes"] } unleash-yggdrasil = "0.4.2" [dev-dependencies] +criterion = "0.4.0" env_logger = "0.10.0" test-case = "2.2.2" testcontainers = "0.14.0" [build-dependencies] shadow-rs = "0.20.0" + +[[bench]] +name = "benchmark" +harness = false \ No newline at end of file diff --git a/server/benches/benchmark.rs b/server/benches/benchmark.rs new file mode 100644 index 00000000..3890cf49 --- /dev/null +++ b/server/benches/benchmark.rs @@ -0,0 +1,37 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use unleash_edge::{ + tokens::simplify, + types::{EdgeToken, TokenType}, +}; + +fn test_token(env: Option<&str>, projects: Vec<&str>) -> EdgeToken { + EdgeToken { + secret: "the-secret".into(), + token_type: Some(TokenType::Client), + environment: env.map(|env| env.into()), + projects: projects.into_iter().map(|p| p.into()).collect(), + expires_at: None, + seen_at: None, + alias: None, + } +} + +fn bench_simplify(c: &mut Criterion) { + let tokens = vec![ + test_token(None, vec!["p1", "p2"]), + test_token(None, vec!["p1"]), + test_token(None, vec!["*"]), + test_token(None, vec!["p3"]), + test_token(Some("env"), vec!["p1", "p2"]), + test_token(Some("env"), vec!["p1"]), + test_token(Some("env"), vec!["p2"]), + test_token(Some("env"), vec!["p2", "p3"]), + ]; + + c.bench_function("simplify_bench", |b| { + b.iter(|| simplify(black_box(&tokens))) + }); +} + +criterion_group!(benches, bench_simplify); +criterion_main!(benches); diff --git a/server/src/data_sources/mod.rs b/server/src/data_sources/mod.rs index 1f519100..b53e0473 100644 --- a/server/src/data_sources/mod.rs +++ b/server/src/data_sources/mod.rs @@ -1,2 +1,2 @@ +pub mod offline_provider; pub mod redis_provider; -pub mod offline_provider; \ No newline at end of file diff --git a/server/src/data_sources/redis_provider.rs b/server/src/data_sources/redis_provider.rs index 00404732..1ab339ae 100644 --- a/server/src/data_sources/redis_provider.rs +++ b/server/src/data_sources/redis_provider.rs @@ -1,4 +1,4 @@ -use std::{sync::RwLock}; +use std::sync::RwLock; use redis::{Client, Commands, RedisError}; use unleash_types::client_features::ClientFeatures; @@ -8,7 +8,7 @@ pub const TOKENS_KEY: &str = "tokens"; use crate::{ error::EdgeError, - types::{EdgeResult, EdgeToken, FeaturesProvider, TokenProvider, EdgeProvider}, + types::{EdgeProvider, EdgeResult, EdgeToken, FeaturesProvider, TokenProvider}, }; pub struct RedisProvider { diff --git a/server/src/error.rs b/server/src/error.rs index 68a7ee97..f21f24b9 100644 --- a/server/src/error.rs +++ b/server/src/error.rs @@ -20,10 +20,9 @@ impl Error for EdgeError {} impl Display for EdgeError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - EdgeError::InvalidBackupFile(path, why_invalid) => write!( - f, - "file at path: {path} was invalid due to {why_invalid}" - ), + EdgeError::InvalidBackupFile(path, why_invalid) => { + write!(f, "file at path: {path} was invalid due to {why_invalid}") + } EdgeError::TlsError => write!(f, "Could not configure TLS"), EdgeError::NoFeaturesFile => write!(f, "No features file located"), EdgeError::AuthorizationDenied => write!(f, "Not allowed to access"), diff --git a/server/src/frontend_api.rs b/server/src/frontend_api.rs index 40b1af87..c30ea6fd 100644 --- a/server/src/frontend_api.rs +++ b/server/src/frontend_api.rs @@ -103,7 +103,7 @@ pub fn configure_frontend_api(cfg: &mut web::ServiceConfig) { mod tests { use std::sync::Arc; - use crate::types::{EdgeProvider, EdgeResult, FeaturesProvider, TokenProvider, EdgeToken}; + use crate::types::{EdgeProvider, EdgeResult, EdgeToken, FeaturesProvider, TokenProvider}; use actix_web::{ http::header::ContentType, test, diff --git a/server/src/lib.rs b/server/src/lib.rs index 41d14269..1f4412bc 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -8,4 +8,6 @@ pub mod frontend_api; pub mod metrics; pub mod types; +pub mod tokens; + pub mod internal_backstage; diff --git a/server/src/main.rs b/server/src/main.rs index c9ed8d6f..5087d1a3 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,6 +1,5 @@ use std::sync::Arc; - use crate::cli::EdgeMode; use actix_cors::Cors; use actix_middleware_etag::Etag; diff --git a/server/src/tls.rs b/server/src/tls.rs index b2a18672..02e22c8a 100644 --- a/server/src/tls.rs +++ b/server/src/tls.rs @@ -3,7 +3,7 @@ use std::{fs::File, io::BufReader}; use rustls::{Certificate, PrivateKey, ServerConfig}; use rustls_pemfile::{certs, pkcs8_private_keys}; -use crate::{cli::TlsOptions}; +use crate::cli::TlsOptions; use unleash_edge::error::EdgeError; pub(crate) fn config(tls_config: TlsOptions) -> Result { diff --git a/server/src/tokens.rs b/server/src/tokens.rs new file mode 100644 index 00000000..b56527c3 --- /dev/null +++ b/server/src/tokens.rs @@ -0,0 +1,99 @@ +use crate::types::EdgeToken; + +pub fn simplify(tokens: &[EdgeToken]) -> Vec { + tokens + .iter() + .filter_map(|token| { + tokens.iter().fold(Some(token.clone()), |acc, current| { + acc.and_then(|lead| { + if current != &lead && current.subsumes(&lead) { + None + } else { + Some(lead) + } + }) + }) + }) + .collect() +} + +#[cfg(test)] +mod tests { + use crate::{ + tokens::simplify, + types::{EdgeToken, TokenType}, + }; + + fn test_token(env: Option<&str>, projects: Vec<&str>) -> EdgeToken { + EdgeToken { + secret: "the-secret".into(), + token_type: Some(TokenType::Client), + environment: env.map(|env| env.into()), + projects: projects.into_iter().map(|p| p.into()).collect(), + expires_at: None, + seen_at: None, + alias: None, + } + } + + #[test] + fn test_case_1() { + let tokens = vec![ + test_token(None, vec!["p1", "p2"]), + test_token(None, vec!["p1"]), + test_token(None, vec!["p1"]), + ]; + + let expected = vec![test_token(None, vec!["p1", "p2"])]; + + assert_eq!(simplify(&tokens), expected); + } + + #[test] + fn test_case_2() { + let tokens = vec![ + test_token(Some("env1"), vec!["p1", "p2"]), + test_token(Some("env1"), vec!["p1"]), + test_token(None, vec!["p1"]), + ]; + let expected = vec![ + test_token(Some("env1"), vec!["p1", "p2"]), + test_token(None, vec!["p1"]), + ]; + + assert_eq!(simplify(&tokens), expected); + } + + #[test] + fn test_case_3() { + let tokens = vec![ + test_token(None, vec!["p1"]), + test_token(None, vec!["*"]), + test_token(None, vec!["p1", "p2"]), + ]; + let expected = vec![test_token(None, vec!["*"])]; + + assert_eq!(simplify(&tokens), expected); + } + + #[test] + fn test_case_4() { + let tokens = vec![ + test_token(None, vec!["p1", "p2"]), + test_token(Some("env"), vec!["p1", "p2"]), + test_token(None, vec!["p1"]), + test_token(Some("env"), vec!["p2", "p3"]), + test_token(None, vec!["*"]), + test_token(Some("env"), vec!["p1"]), + test_token(None, vec!["p3"]), + test_token(Some("env"), vec!["p2"]), + ]; + let expected = vec![ + test_token(Some("env"), vec!["p1", "p2"]), + test_token(Some("env"), vec!["p2", "p3"]), + test_token(None, vec!["*"]), + ]; + + assert_eq!(simplify(&tokens), expected); + } +} diff --git a/server/src/types.rs b/server/src/types.rs index f26068e5..bea5bd9c 100644 --- a/server/src/types.rs +++ b/server/src/types.rs @@ -13,7 +13,7 @@ use actix_web::{ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use shadow_rs::shadow; -use tracing::warn; +use tracing::{info, warn}; use unleash_types::client_features::ClientFeatures; pub type EdgeJsonResult = Result, EdgeError>; @@ -50,6 +50,32 @@ impl EdgeToken { alias: None, } } + + pub fn subsumes(&self, other: &EdgeToken) -> bool { + info!( + "token_type equal? {:?}", + self.token_type == other.token_type + ); + info!( + "Environment subsumes? {:?}", + self.environment == other.environment || self.environment == Some("*".into()) + ); + info!( + "Have more projects? {:?}", + self.projects.len() >= other.projects.len() + ); + info!( + "All projects contained {:?} into {:?}? {:?}", + self.projects, + other.projects, + self.projects.iter().all(|p| other.projects.contains(p)) + ); + return self.token_type == other.token_type + && self.environment == other.environment + && (self.projects.contains(&"*".into()) + || (self.projects.len() >= other.projects.len() + && other.projects.iter().all(|p| self.projects.contains(p)))); + } } impl FromRequest for EdgeToken { @@ -215,7 +241,26 @@ mod tests { use test_case::test_case; use tracing::warn; - use crate::types::EdgeToken; + use crate::types::{EdgeToken, TokenType}; + + fn test_str(token: &str) -> EdgeToken { + EdgeToken::from_str( + &(token.to_owned() + ".614a75cf68bef8703aa1bd8304938a81ec871f86ea40c975468eabd6"), + ) + .unwrap() + } + + fn test_token(env: Option<&str>, projects: Vec<&str>) -> EdgeToken { + EdgeToken { + secret: "the-secret".into(), + token_type: Some(TokenType::Client), + environment: env.map(|env| env.into()), + projects: projects.into_iter().map(|p| p.into()).collect(), + expires_at: None, + seen_at: None, + alias: None, + } + } #[test_case("943ca9171e2c884c545c5d82417a655fb77cec970cc3b78a8ff87f4406b495d0"; "old java client token")] #[test_case("demo-app:production.614a75cf68bef8703aa1bd8304938a81ec871f86ea40c975468eabd6"; "demo token with project and environment")] @@ -233,4 +278,48 @@ mod tests { } } } + + #[test_case( + "demo-app:production", + "demo-app:production" + => true + ; "idepmotency")] + #[test_case( + "aproject:production", + "another:production" + => false + ; "project mismatch")] + #[test_case( + "demo-app:development", + "demo-app:production" + => false + ; "environment mismatch")] + #[test_case( + "*:production", + "demo-app:production" + => true + ; "* subsumes a project token")] + fn edge_token_subsumes_edge_token(token1: &str, token2: &str) -> bool { + let t1 = test_str(token1); + let t2 = test_str(token2); + t1.subsumes(&t2) + } + + #[test] + fn edge_token_unrleated_by_subsume() { + let t1 = test_str("demo-app:production"); + let t2 = test_str("another:production"); + assert!(!t1.subsumes(&t2)); + assert!(!t2.subsumes(&t1)); + } + + #[test] + fn edge_token_does_not_subsume_if_projects_is_subset_of_other_tokens_project() { + let token1 = test_token(None, vec!["p1", "p2"]); + + let token2 = test_token(None, vec!["p1"]); + + assert!(token1.subsumes(&token2)); + assert!(!token2.subsumes(&token1)); + } } diff --git a/server/tests/redis_test.rs b/server/tests/redis_test.rs index 3079992e..81b310f2 100644 --- a/server/tests/redis_test.rs +++ b/server/tests/redis_test.rs @@ -16,8 +16,7 @@ async fn redis_provider_returns_expected_data() { let mut client = redis::Client::open(url.clone()).unwrap(); - let content = - fs::read_to_string("../examples/features.json".to_string()).expect("Could not read file"); + let content = fs::read_to_string("../examples/features.json").expect("Could not read file"); //Wants a type annotation but we don't care about the result so we immediately discard the data coming back let _: () = client.set(FEATURE_KEY, content).unwrap(); From 8aac668f33d3aacddafc69854a9838c080a733c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Fournier?= Date: Wed, 1 Feb 2023 14:15:21 +0100 Subject: [PATCH 2/6] Remove info lines --- server/src/types.rs | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/server/src/types.rs b/server/src/types.rs index 3b4e9b6f..bf1311ea 100644 --- a/server/src/types.rs +++ b/server/src/types.rs @@ -13,7 +13,7 @@ use actix_web::{ use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use shadow_rs::shadow; -use tracing::{info, warn}; +use tracing::warn; use unleash_types::client_features::ClientFeatures; pub type EdgeJsonResult = Result, EdgeError>; @@ -52,24 +52,6 @@ impl EdgeToken { } pub fn subsumes(&self, other: &EdgeToken) -> bool { - info!( - "token_type equal? {:?}", - self.token_type == other.token_type - ); - info!( - "Environment subsumes? {:?}", - self.environment == other.environment || self.environment == Some("*".into()) - ); - info!( - "Have more projects? {:?}", - self.projects.len() >= other.projects.len() - ); - info!( - "All projects contained {:?} into {:?}? {:?}", - self.projects, - other.projects, - self.projects.iter().all(|p| other.projects.contains(p)) - ); return self.token_type == other.token_type && self.environment == other.environment && (self.projects.contains(&"*".into()) From ba36dcbf5adfaaae939eaf809e22f8f0dc985576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Fournier?= Date: Wed, 1 Feb 2023 14:39:57 +0100 Subject: [PATCH 3/6] Remove benchmarks --- Cargo.lock | 263 +----------------------------------- server/Cargo.toml | 7 - server/benches/benchmark.rs | 37 ----- server/src/tokens.rs | 2 +- 4 files changed, 3 insertions(+), 306 deletions(-) delete mode 100644 server/benches/benchmark.rs diff --git a/Cargo.lock b/Cargo.lock index 9cf5e6ae..60eda32e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -297,12 +297,6 @@ dependencies = [ "libc", ] -[[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - [[package]] name = "ansi_term" version = "0.12.1" @@ -432,12 +426,6 @@ dependencies = [ "bytes", ] -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - [[package]] name = "cc" version = "1.0.78" @@ -469,33 +457,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "ciborium" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369" - -[[package]] -name = "ciborium-ll" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b" -dependencies = [ - "ciborium-io", - "half", -] - [[package]] name = "clap" version = "2.34.0" @@ -506,23 +467,11 @@ dependencies = [ "atty", "bitflags", "strsim 0.8.0", - "textwrap 0.11.0", + "textwrap", "unicode-width", "vec_map", ] -[[package]] -name = "clap" -version = "3.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" -dependencies = [ - "bitflags", - "clap_lex 0.2.4", - "indexmap", - "textwrap 0.16.0", -] - [[package]] name = "clap" version = "4.1.4" @@ -531,7 +480,7 @@ checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76" dependencies = [ "bitflags", "clap_derive", - "clap_lex 0.3.1", + "clap_lex", "is-terminal", "once_cell", "strsim 0.10.0", @@ -551,15 +500,6 @@ dependencies = [ "syn", ] -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - [[package]] name = "clap_lex" version = "0.3.1" @@ -665,42 +605,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "criterion" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" -dependencies = [ - "anes", - "atty", - "cast", - "ciborium", - "clap 3.2.23", - "criterion-plot", - "itertools", - "lazy_static", - "num-traits", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools", -] - [[package]] name = "crossbeam-channel" version = "0.5.6" @@ -711,30 +615,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "crossbeam-deque" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - [[package]] name = "crossbeam-utils" version = "0.8.14" @@ -945,12 +825,6 @@ dependencies = [ "clap 2.34.0", ] -[[package]] -name = "either" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" - [[package]] name = "encoding_rs" version = "0.8.31" @@ -1161,12 +1035,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - [[package]] name = "hashbrown" version = "0.12.3" @@ -1326,15 +1194,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06d198e9919d9822d5f7083ba8530e04de87841eaf21ead9af8f2304efd57c89" -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.5" @@ -1468,15 +1327,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - [[package]] name = "mime" version = "0.3.16" @@ -1564,12 +1414,6 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" -[[package]] -name = "oorandom" -version = "11.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" - [[package]] name = "opentelemetry" version = "0.18.0" @@ -1747,34 +1591,6 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" -[[package]] -name = "plotters" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" - -[[package]] -name = "plotters-svg" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" -dependencies = [ - "plotters-backend", -] - [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1889,28 +1705,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rayon" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - [[package]] name = "redis" version = "0.22.3" @@ -2025,15 +1819,6 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - [[package]] name = "scopeguard" version = "1.1.0" @@ -2303,12 +2088,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "textwrap" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" - [[package]] name = "thiserror" version = "1.0.38" @@ -2378,16 +2157,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "tinyvec" version = "1.6.0" @@ -2516,20 +2285,6 @@ dependencies = [ "tracing-core", ] -[[package]] -name = "tracing-opentelemetry" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ebb87a95ea13271332df069020513ab70bdb5637ca42d6e492dc3bbbad48de" -dependencies = [ - "once_cell", - "opentelemetry", - "tracing", - "tracing-core", - "tracing-log", - "tracing-subscriber", -] - [[package]] name = "tracing-serde" version = "0.1.3" @@ -2637,13 +2392,11 @@ version = "0.0.0" dependencies = [ "actix-cors", "actix-middleware-etag", - "actix-tls", "actix-web", "actix-web-opentelemetry", "anyhow", "chrono", "clap 4.1.4", - "criterion", "dashmap", "dotenv", "env_logger", @@ -2660,7 +2413,6 @@ dependencies = [ "testcontainers", "tokio", "tracing", - "tracing-opentelemetry", "tracing-subscriber", "unleash-types", "unleash-yggdrasil", @@ -2766,17 +2518,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "walkdir" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" -dependencies = [ - "same-file", - "winapi", - "winapi-util", -] - [[package]] name = "wasi" version = "0.10.0+wasi-snapshot-preview1" diff --git a/server/Cargo.toml b/server/Cargo.toml index 07e378de..5dfc130e 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -11,7 +11,6 @@ homepage = "https://github.com/Unleash/unleash-edge" [dependencies] actix-cors = "0.6.4" actix-middleware-etag = "0.1.1" -actix-tls = { version = "3.0.3", features = ["rustls"] } actix-web = { version = "4.3.0", features = ["rustls"] } actix-web-opentelemetry = { version = "0.13.0", features = ["metrics", "metrics-prometheus"] } @@ -31,20 +30,14 @@ serde_json = "1.0.91" shadow-rs = "0.20.0" tokio = { version = "1.25.0", features = ["macros", "rt-multi-thread", "tracing"] } tracing = { version = "0.1.37", features = ["log"] } -tracing-opentelemetry = "0.18.0" tracing-subscriber = { version = "0.3.16", features = ["json", "env-filter"] } unleash-types = { version = "0.7.0", features = ["openapi", "hashes"] } unleash-yggdrasil = "0.4.2" [dev-dependencies] -criterion = "0.4.0" env_logger = "0.10.0" test-case = "2.2.2" testcontainers = "0.14.0" [build-dependencies] shadow-rs = "0.20.0" - -[[bench]] -name = "benchmark" -harness = false \ No newline at end of file diff --git a/server/benches/benchmark.rs b/server/benches/benchmark.rs deleted file mode 100644 index 3890cf49..00000000 --- a/server/benches/benchmark.rs +++ /dev/null @@ -1,37 +0,0 @@ -use criterion::{black_box, criterion_group, criterion_main, Criterion}; -use unleash_edge::{ - tokens::simplify, - types::{EdgeToken, TokenType}, -}; - -fn test_token(env: Option<&str>, projects: Vec<&str>) -> EdgeToken { - EdgeToken { - secret: "the-secret".into(), - token_type: Some(TokenType::Client), - environment: env.map(|env| env.into()), - projects: projects.into_iter().map(|p| p.into()).collect(), - expires_at: None, - seen_at: None, - alias: None, - } -} - -fn bench_simplify(c: &mut Criterion) { - let tokens = vec![ - test_token(None, vec!["p1", "p2"]), - test_token(None, vec!["p1"]), - test_token(None, vec!["*"]), - test_token(None, vec!["p3"]), - test_token(Some("env"), vec!["p1", "p2"]), - test_token(Some("env"), vec!["p1"]), - test_token(Some("env"), vec!["p2"]), - test_token(Some("env"), vec!["p2", "p3"]), - ]; - - c.bench_function("simplify_bench", |b| { - b.iter(|| simplify(black_box(&tokens))) - }); -} - -criterion_group!(benches, bench_simplify); -criterion_main!(benches); diff --git a/server/src/tokens.rs b/server/src/tokens.rs index b56527c3..c125d3d7 100644 --- a/server/src/tokens.rs +++ b/server/src/tokens.rs @@ -1,6 +1,6 @@ use crate::types::EdgeToken; -pub fn simplify(tokens: &[EdgeToken]) -> Vec { +pub(crate) fn simplify(tokens: &[EdgeToken]) -> Vec { tokens .iter() .filter_map(|token| { From eb6b7e271cba758bea89c74ab1ebd76217695c41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Fournier?= Date: Wed, 1 Feb 2023 14:40:24 +0100 Subject: [PATCH 4/6] Remove benchmarks --- server/src/tokens.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/tokens.rs b/server/src/tokens.rs index c125d3d7..d9539355 100644 --- a/server/src/tokens.rs +++ b/server/src/tokens.rs @@ -1,5 +1,6 @@ use crate::types::EdgeToken; +#[allow(dead_code)] // until used pub(crate) fn simplify(tokens: &[EdgeToken]) -> Vec { tokens .iter() From 3b8643242d5c897647ebeaab767d87eeafbd7950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Fournier?= Date: Wed, 1 Feb 2023 14:45:03 +0100 Subject: [PATCH 5/6] Add better test names --- server/src/tokens.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/tokens.rs b/server/src/tokens.rs index d9539355..aacaf692 100644 --- a/server/src/tokens.rs +++ b/server/src/tokens.rs @@ -38,7 +38,7 @@ mod tests { } #[test] - fn test_case_1() { + fn test_case_1_token_with_two_projects_subsumes_tokens_having_individually_each_token() { let tokens = vec![ test_token(None, vec!["p1", "p2"]), test_token(None, vec!["p1"]), @@ -51,7 +51,7 @@ mod tests { } #[test] - fn test_case_2() { + fn test_case_2_when_two_environments_are_different_we_have_at_least_two_tokens() { let tokens = vec![ test_token(Some("env1"), vec!["p1", "p2"]), test_token(Some("env1"), vec!["p1"]), @@ -66,7 +66,7 @@ mod tests { } #[test] - fn test_case_3() { + fn test_case_3_star_token_subsumes_all_tokens() { let tokens = vec![ test_token(None, vec!["p1"]), test_token(None, vec!["*"]), @@ -78,7 +78,7 @@ mod tests { } #[test] - fn test_case_4() { + fn test_case_4_when_a_project_is_shared_between_two_tokens_we_simplify_as_much_as_we_can() { let tokens = vec![ test_token(None, vec!["p1", "p2"]), test_token(Some("env"), vec!["p1", "p2"]), From a30aea97d94079ad3148b8a344ad062eb8a0169a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Fournier?= Date: Wed, 1 Feb 2023 15:01:41 +0100 Subject: [PATCH 6/6] Use derive default EdgeToken for tests --- server/src/data_sources/memory_provider.rs | 16 ---------------- server/src/tokens.rs | 11 ++--------- server/src/types.rs | 9 +++------ 3 files changed, 5 insertions(+), 31 deletions(-) diff --git a/server/src/data_sources/memory_provider.rs b/server/src/data_sources/memory_provider.rs index 26edf497..5accebfc 100644 --- a/server/src/data_sources/memory_provider.rs +++ b/server/src/data_sources/memory_provider.rs @@ -62,22 +62,6 @@ mod test { } } - //Yes, Clippy is correct but right now, this is test code and I don't want add a derive that's broken for prod code - #[allow(clippy::derivable_impls)] - impl Default for EdgeToken { - fn default() -> Self { - Self { - secret: Default::default(), - token_type: Default::default(), - environment: Default::default(), - projects: Default::default(), - expires_at: Default::default(), - seen_at: Default::default(), - alias: Default::default(), - } - } - } - #[test] fn memory_provider_correctly_deduplicates_tokens() { let mut provider = MemoryProvider::default(); diff --git a/server/src/tokens.rs b/server/src/tokens.rs index aacaf692..29d7585c 100644 --- a/server/src/tokens.rs +++ b/server/src/tokens.rs @@ -20,20 +20,13 @@ pub(crate) fn simplify(tokens: &[EdgeToken]) -> Vec { #[cfg(test)] mod tests { - use crate::{ - tokens::simplify, - types::{EdgeToken, TokenType}, - }; + use crate::{tokens::simplify, types::EdgeToken}; fn test_token(env: Option<&str>, projects: Vec<&str>) -> EdgeToken { EdgeToken { - secret: "the-secret".into(), - token_type: Some(TokenType::Client), environment: env.map(|env| env.into()), projects: projects.into_iter().map(|p| p.into()).collect(), - expires_at: None, - seen_at: None, - alias: None, + ..EdgeToken::default() } } diff --git a/server/src/types.rs b/server/src/types.rs index e49709cf..9547727c 100644 --- a/server/src/types.rs +++ b/server/src/types.rs @@ -48,6 +48,7 @@ impl ClientFeaturesRequest { } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(test, derive(Default))] #[serde(rename_all = "camelCase")] pub struct EdgeToken { pub secret: String, @@ -250,7 +251,7 @@ mod tests { use test_case::test_case; use tracing::warn; - use crate::types::{EdgeToken, TokenType}; + use crate::types::EdgeToken; fn test_str(token: &str) -> EdgeToken { EdgeToken::from_str( @@ -261,13 +262,9 @@ mod tests { fn test_token(env: Option<&str>, projects: Vec<&str>) -> EdgeToken { EdgeToken { - secret: "the-secret".into(), - token_type: Some(TokenType::Client), environment: env.map(|env| env.into()), projects: projects.into_iter().map(|p| p.into()).collect(), - expires_at: None, - seen_at: None, - alias: None, + ..EdgeToken::default() } }