Skip to content

Commit e354aed

Browse files
committed
Support for renamed redis commands
fixes #29
1 parent 8094951 commit e354aed

File tree

5 files changed

+96
-6
lines changed

5 files changed

+96
-6
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## Unreleased
2+
- Add support for renamed redis commands #29
3+
14
## 3.3.0
25
- Add channel to the event #46
36

docs/index.asciidoc

100644100755
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
5353
| <<plugins-{type}s-{plugin}-ssl>> |<<boolean,boolean>>|No
5454
| <<plugins-{type}s-{plugin}-threads>> |<<number,number>>|No
5555
| <<plugins-{type}s-{plugin}-timeout>> |<<number,number>>|No
56+
| <<plugins-{type}s-{plugin}-command_map>> |<<hash,hash>>|No
5657
|=======================================================================
5758

5859
Also see <<plugins-{type}s-{plugin}-common-options>> for a list of options supported by all
@@ -154,7 +155,15 @@ Enable SSL support.
154155

155156
Initial connection timeout in seconds.
156157

158+
[id="plugins-{type}s-{plugin}-command_map"]
159+
===== `command_map`
157160

161+
* Value type is <<hash,hash>>
162+
* There is no default value for this setting.
163+
* key is the default command name, value is the renamed command.
164+
165+
Configure renamed redis commands in the form of "oldname" => "newname".
166+
Redis allows for the renaming or disabling of commands in its protocol, see: https://redis.io/topics/security
158167

159168
[id="plugins-{type}s-{plugin}-common-options"]
160169
include::{include_path}/{type}.asciidoc[]

lib/logstash/inputs/redis.rb

100644100755
Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,12 @@ module LogStash module Inputs class Redis < LogStash::Inputs::Threadable
5656
# The number of events to return from Redis using EVAL.
5757
config :batch_count, :validate => :number, :default => 125
5858

59+
# Redefined Redis commands to be passed to the Redis client.
60+
config :command_map, :validate => :hash, :default => {}
61+
5962
public
6063
# public API
61-
# use to store a proc that can provide a redis instance or mock
64+
# use to store a proc that can provide a Redis instance or mock
6265
def add_external_redis_builder(builder) #callable
6366
@redis_builder = builder
6467
self
@@ -151,18 +154,27 @@ def internal_redis_builder
151154
# private
152155
def connect
153156
redis = new_redis_instance
157+
158+
# register any renamed Redis commands
159+
if @command_map and not @command_map.empty?
160+
client_command_map = redis.client.command_map
161+
@command_map.each do |name, renamed|
162+
client_command_map[name.to_sym] = renamed.to_sym
163+
end
164+
end
165+
154166
load_batch_script(redis) if batched? && is_list_type?
155167
redis
156168
end # def connect
157169

158170
# private
159171
def load_batch_script(redis)
160172
#A Redis Lua EVAL script to fetch a count of keys
161-
redis_script = <<EOF
162-
local batchsize = tonumber(ARGV[1])
163-
local result = redis.call('lrange', KEYS[1], 0, batchsize)
164-
redis.call('ltrim', KEYS[1], batchsize + 1, -1)
165-
return result
173+
redis_script = <<EOF
174+
local batchsize = tonumber(ARGV[1])
175+
local result = redis.call(\'#{@command_map.fetch('lrange', 'lrange')}\', KEYS[1], 0, batchsize)
176+
redis.call(\'#{@command_map.fetch('ltrim', 'ltrim')}\', KEYS[1], batchsize + 1, -1)
177+
return result
166178
EOF
167179
@redis_script_sha = redis.script(:load, redis_script)
168180
end

logstash-input-redis.gemspec

100644100755
File mode changed.

spec/inputs/redis_spec.rb

100644100755
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ def process(conf, event_count)
7676
let(:cfg) { {'key' => 'foo', 'data_type' => data_type, 'batch_count' => batch_count} }
7777
let(:quit_calls) { [:quit] }
7878
let(:accumulator) { [] }
79+
let(:command_map) { {} }
7980

8081
subject do
8182
LogStash::Plugin.lookup("input", "redis")
@@ -88,6 +89,71 @@ def process(conf, event_count)
8889
end
8990
end
9091

92+
context 'renamed redis commands' do
93+
let(:cfg) {
94+
{'key' => 'foo',
95+
'data_type' => data_type,
96+
'command_map' =>
97+
{
98+
'blpop' => 'testblpop',
99+
'evalsha' => 'testevalsha',
100+
'lrange' => 'testlrange',
101+
'ltrim' => 'testltrim',
102+
'script' => 'testscript',
103+
'subscribe' => 'testsubscribe',
104+
'psubscribe' => 'testpsubscribe',
105+
},
106+
'batch_count' => 2
107+
}
108+
}
109+
110+
before do
111+
subject.register
112+
allow(redis).to receive(:connected?)
113+
allow(redis).to receive(:client).and_return(connection)
114+
allow(connection).to receive(:command_map).and_return(command_map)
115+
end
116+
117+
it 'sets the renamed commands in the command map' do
118+
allow(redis).to receive(:script)
119+
allow(redis).to receive(:evalsha).and_return([])
120+
121+
tt = Thread.new do
122+
sleep 0.01
123+
subject.do_stop
124+
end
125+
126+
subject.run(accumulator)
127+
tt.join
128+
129+
expect(command_map[:blpop]).to eq cfg['command_map']['blpop'].to_sym
130+
expect(command_map[:evalsha]).to eq cfg['command_map']['evalsha'].to_sym
131+
expect(command_map[:lrange]).to eq cfg['command_map']['lrange'].to_sym
132+
expect(command_map[:ltrim]).to eq cfg['command_map']['ltrim'].to_sym
133+
expect(command_map[:script]).to eq cfg['command_map']['script'].to_sym
134+
expect(command_map[:subscribe]).to eq cfg['command_map']['subscribe'].to_sym
135+
expect(command_map[:psubscribe]).to eq cfg['command_map']['psubscribe'].to_sym
136+
end
137+
138+
it 'loads the batch script with the renamed command' do
139+
capture = nil
140+
allow(redis).to receive(:script) { |load, lua_script| capture = lua_script }
141+
allow(redis).to receive(:evalsha).and_return([])
142+
143+
tt = Thread.new do
144+
sleep 0.01
145+
subject.do_stop
146+
end
147+
148+
subject.run(accumulator)
149+
tt.join
150+
151+
expect(capture).to include "redis.call('#{cfg['command_map']['lrange']}', KEYS[1], 0, batchsize)"
152+
expect(capture).to include "redis.call('#{cfg['command_map']['ltrim']}', KEYS[1], batchsize + 1, -1)"
153+
end
154+
end
155+
156+
91157
context 'runtime for list data_type' do
92158
before do
93159
subject.register

0 commit comments

Comments
 (0)