Skip to content

Commit 6be84d1

Browse files
author
Meir Shpilraien (Spielrein)
authored
Added support for _proxy-filtered flag. (#366)
The new flag is an enterprise only flag. The new flag will make sure the command will not appeared on slow log, command command, and other location where we do not want to expose it.
1 parent a6156e3 commit 6be84d1

File tree

5 files changed

+61
-13
lines changed

5 files changed

+61
-13
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ commands:
114114
- run:
115115
name: patch macos tests # Avoid AVX with Regex with CircleCI since virtualization layer doesn't support it. Use sed to replace the relevant entry in cargo.toml
116116
command: |
117-
if [[ $(uname -s) == Darwin ]]; then sed -i 's/regex = "1"/regex = { version = "1", features = ["perf", "unicode"] }/g' Cargo.toml; fi
117+
if [[ $(uname -s) == Darwin ]]; then sed -i 's/regex = "1"/regex = { version = "1", features = ["perf", "unicode"], default-features = false }/g' Cargo.toml; fi
118118
cat Cargo.toml
119119
- restore_cache:
120120
keys:

redismodule-rs-macros/src/command.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,21 @@ impl From<&RedisCommandFlags> for &'static str {
109109
}
110110
}
111111

112+
#[derive(Debug, Deserialize)]
113+
pub enum RedisEnterpriseCommandFlags {
114+
/// A special enterprise only flag, make sure the commands marked with this flag will not be expose to
115+
/// user via `command` command or on slow log.
116+
ProxyFiltered,
117+
}
118+
119+
impl From<&RedisEnterpriseCommandFlags> for &'static str {
120+
fn from(value: &RedisEnterpriseCommandFlags) -> Self {
121+
match value {
122+
RedisEnterpriseCommandFlags::ProxyFiltered => "_proxy-filtered",
123+
}
124+
}
125+
}
126+
112127
#[derive(Debug, Deserialize)]
113128
pub enum RedisCommandKeySpecFlags {
114129
/// Read-Only. Reads the value of the key, but doesn't necessarily return it.
@@ -212,6 +227,7 @@ pub struct KeySpecArg {
212227
struct Args {
213228
name: Option<String>,
214229
flags: Vec<RedisCommandFlags>,
230+
enterprise_flags: Option<Vec<RedisEnterpriseCommandFlags>>,
215231
summary: Option<String>,
216232
complexity: Option<String>,
217233
since: Option<String>,
@@ -240,10 +256,7 @@ pub(crate) fn redis_command(attr: TokenStream, item: TokenStream) -> TokenStream
240256

241257
let original_function_name = func.sig.ident.clone();
242258

243-
let c_function_name = Ident::new(
244-
&format!("_inner_{}", func.sig.ident),
245-
func.sig.ident.span(),
246-
);
259+
let c_function_name = Ident::new(&format!("_inner_{}", func.sig.ident), func.sig.ident.span());
247260

248261
let get_command_info_function_name = Ident::new(
249262
&format!("_inner_get_command_info_{}", func.sig.ident),
@@ -262,6 +275,19 @@ pub(crate) fn redis_command(attr: TokenStream, item: TokenStream) -> TokenStream
262275
.trim()
263276
.to_owned();
264277
let flags_literal = quote!(#flags_str);
278+
let enterprise_flags_str = args
279+
.enterprise_flags
280+
.map(|v| {
281+
v.into_iter()
282+
.fold(String::new(), |s, v| {
283+
format!("{} {}", s, Into::<&'static str>::into(&v))
284+
})
285+
.trim()
286+
.to_owned()
287+
})
288+
.unwrap_or_default();
289+
290+
let enterprise_flags_literal = quote!(#enterprise_flags_str);
265291
let summary_literal = to_token_stream(args.summary);
266292
let complexity_literal = to_token_stream(args.complexity);
267293
let since_literal = to_token_stream(args.since);
@@ -362,6 +388,7 @@ pub(crate) fn redis_command(attr: TokenStream, item: TokenStream) -> TokenStream
362388
Ok(redis_module::commands::CommandInfo::new(
363389
#name_literal.to_owned(),
364390
Some(#flags_literal.to_owned()),
391+
Some(#enterprise_flags_literal.to_owned()),
365392
#summary_literal,
366393
#complexity_literal,
367394
#since_literal,

redismodule-rs-macros/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ mod redis_value;
99
/// This proc macro allow to specify that the follow function is a Redis command.
1010
/// The macro accept the following arguments that discribe the command properties:
1111
/// * name (optional) - The command name. in case not given, the function name will be taken.
12-
/// * flags - An array of `RedisCommandFlags`.
12+
/// * flags - An array of [`command::RedisCommandFlags`].
13+
/// * enterprise_flags - An array of [`command::RedisEnterpriseCommandFlags`].
1314
/// * summary (optional) - Command summary
1415
/// * complexity (optional) - Command compexity
1516
/// * since (optional) - At which module version the command was first introduce

src/context/commands.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ type CommandCallback =
315315
pub struct CommandInfo {
316316
name: String,
317317
flags: Option<String>,
318+
enterprise_flags: Option<String>,
318319
summary: Option<String>,
319320
complexity: Option<String>,
320321
since: Option<String>,
@@ -328,6 +329,7 @@ impl CommandInfo {
328329
pub fn new(
329330
name: String,
330331
flags: Option<String>,
332+
enterprise_flags: Option<String>,
331333
summary: Option<String>,
332334
complexity: Option<String>,
333335
since: Option<String>,
@@ -339,6 +341,7 @@ impl CommandInfo {
339341
CommandInfo {
340342
name,
341343
flags,
344+
enterprise_flags,
342345
summary,
343346
complexity,
344347
since,
@@ -368,16 +371,15 @@ api! {[
368371
],
369372
/// Register all the commands located on `COMMNADS_LIST`.
370373
fn register_commands_internal(ctx: &Context) -> Result<(), RedisError> {
374+
let is_enterprise = ctx.is_enterprise();
371375
COMMANDS_LIST.iter().try_for_each(|command| {
372376
let command_info = command()?;
373377
let name: CString = CString::new(command_info.name.as_str()).unwrap();
374-
let flags = CString::new(
375-
command_info
376-
.flags
377-
.as_deref()
378-
.unwrap_or(""),
379-
)
380-
.unwrap();
378+
let mut flags = command_info.flags.as_deref().unwrap_or("").to_owned();
379+
if is_enterprise {
380+
flags = format!("{flags} {}", command_info.enterprise_flags.as_deref().unwrap_or("")).trim().to_owned();
381+
}
382+
let flags = CString::new(flags).map_err(|e| RedisError::String(e.to_string()))?;
381383

382384
if unsafe {
383385
RedisModule_CreateCommand(

src/context/mod.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,24 @@ impl Context {
850850
unsafe { RedisModule_AvoidReplicaTraffic() == 1 }
851851
}
852852
);
853+
854+
/// Return [Ok(true)] is the current Redis deployment is enterprise, otherwise [Ok(false)].
855+
/// Return error in case it was not possible to determind the deployment.
856+
fn is_enterprise_internal(&self) -> Result<bool, RedisError> {
857+
let info_res = self.call("info", &["server"])?;
858+
match info_res {
859+
RedisValue::BulkRedisString(res) => Ok(res.try_as_str()?.contains("rlec_version:")),
860+
_ => Err(RedisError::Str("Mismatch call reply type")),
861+
}
862+
}
863+
864+
/// Return `true` is the current Redis deployment is enterprise, otherwise `false`.
865+
pub fn is_enterprise(&self) -> bool {
866+
self.is_enterprise_internal().unwrap_or_else(|e| {
867+
log::error!("Failed getting deployment type, assuming oss. Error: {e}.");
868+
false
869+
})
870+
}
853871
}
854872

855873
extern "C" fn post_notification_job_free_callback<F: FnOnce(&Context)>(pd: *mut c_void) {

0 commit comments

Comments
 (0)