redis_web_manager 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.coveralls.yml +2 -0
- data/.travis.yml +1 -0
- data/Gemfile.lock +23 -1
- data/README.md +95 -4
- data/Rakefile +1 -1
- data/app/controllers/redis_web_manager/actions_controller.rb +15 -3
- data/app/controllers/redis_web_manager/application_controller.rb +4 -0
- data/app/controllers/redis_web_manager/clients_controller.rb +1 -1
- data/app/controllers/redis_web_manager/configuration_controller.rb +1 -1
- data/app/controllers/redis_web_manager/dashboard_controller.rb +23 -3
- data/app/controllers/redis_web_manager/information_controller.rb +1 -1
- data/app/controllers/redis_web_manager/keys_controller.rb +135 -0
- data/app/helpers/redis_web_manager/application_helper.rb +16 -0
- data/app/helpers/redis_web_manager/dashboard_helper.rb +1 -1
- data/app/views/redis_web_manager/dashboard/index.html.erb +20 -1
- data/app/views/redis_web_manager/keys/edit.html.erb +14 -0
- data/app/views/redis_web_manager/keys/index.html.erb +54 -0
- data/app/views/redis_web_manager/keys/show.html.erb +30 -0
- data/app/views/redis_web_manager/shared/_header.html.erb +12 -2
- data/app/views/redis_web_manager/shared/_status.html.erb +2 -2
- data/bin/rails +1 -1
- data/config/routes.rb +8 -0
- data/lib/redis_web_manager.rb +1 -1
- data/lib/redis_web_manager/action.rb +1 -1
- data/lib/redis_web_manager/data.rb +16 -0
- data/lib/redis_web_manager/version.rb +1 -1
- data/redis_web_manager.gemspec +6 -4
- data/spec/controllers/redis_web_manager/actions_controller_spec.rb +16 -1
- data/spec/controllers/redis_web_manager/clients_controller_spec.rb +1 -1
- data/spec/controllers/redis_web_manager/keys_controller_spec.rb +139 -0
- data/spec/helpers/application_helper_spec.rb +13 -1
- data/spec/helpers/dashboard_helper_spec.rb +1 -1
- data/spec/redis_web_manager_data_spec.rb +23 -0
- data/spec/routing/actions_controller_spec.rb +6 -0
- data/spec/routing/keys_controller_spec.rb +39 -0
- data/spec/spec_helper.rb +6 -0
- metadata +295 -342
@@ -2,6 +2,22 @@
|
|
2
2
|
|
3
3
|
module RedisWebManager
|
4
4
|
module ApplicationHelper
|
5
|
+
require 'pagy'
|
6
|
+
|
7
|
+
include ::Pagy::Frontend
|
8
|
+
|
9
|
+
def status(value)
|
10
|
+
if value
|
11
|
+
content_tag(:kbd, 'ON', class: 'bg-success bounce')
|
12
|
+
else
|
13
|
+
content_tag(:kbd, 'OFF', class: 'bg-danger bounce')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def url(value)
|
18
|
+
content_tag(:kbd, value, class: 'bg-dark')
|
19
|
+
end
|
20
|
+
|
5
21
|
def expire(value)
|
6
22
|
if value == -1
|
7
23
|
'No expiration date'
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<div class="container">
|
2
2
|
<%= render 'redis_web_manager/shared/status' %>
|
3
3
|
<div class="row my-4">
|
4
|
-
<div class="col-sm-12 col-md-
|
4
|
+
<div class="col-sm-12 col-md-9">
|
5
5
|
<div class="row mb-4">
|
6
6
|
<div class="col-12">
|
7
7
|
<div class="card">
|
@@ -45,5 +45,24 @@
|
|
45
45
|
</div>
|
46
46
|
</div>
|
47
47
|
</div>
|
48
|
+
<div class="col-sm-12 col-md-3">
|
49
|
+
<div class="card">
|
50
|
+
<div class="card-header">
|
51
|
+
<h5 class="card-title mb-0">
|
52
|
+
Information
|
53
|
+
</h5>
|
54
|
+
</div>
|
55
|
+
<div class="card-body p-0">
|
56
|
+
<ul class="list-group list-group-flush">
|
57
|
+
<% @information.each do |data| %>
|
58
|
+
<li class="list-group-item d-flex justify-content-between">
|
59
|
+
<div class="font-weight-normal"><%= data[:name] %></div>
|
60
|
+
<div class="font-weight-light"><%= data[:value] %></div>
|
61
|
+
</li>
|
62
|
+
<% end %>
|
63
|
+
</ul>
|
64
|
+
</div>
|
65
|
+
</div>
|
66
|
+
</div>
|
48
67
|
</div>
|
49
68
|
</div>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<div class="container">
|
2
|
+
<div class="row my-4">
|
3
|
+
<div class="col-sm-6 offset-sm-3">
|
4
|
+
<%= form_tag update_key_path, method: :put, class: "form-horizontal center" do %>
|
5
|
+
<div class="form-group">
|
6
|
+
<%= label_tag :key, "Name key:", class: "control-label" %>
|
7
|
+
<%= text_field_tag :key, @key[:key], class: "form-control" %>
|
8
|
+
<%= hidden_field_tag :old_key, @key[:key] %>
|
9
|
+
</div>
|
10
|
+
<%= submit_tag "Submit", class: "btn btn-default btn-primary" %>
|
11
|
+
<% end %>
|
12
|
+
</div>
|
13
|
+
</div>
|
14
|
+
</div>
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<div class="container">
|
2
|
+
<%= render 'redis_web_manager/shared/status' %>
|
3
|
+
<div class="row my-4">
|
4
|
+
<div class="col-12">
|
5
|
+
<div class="card">
|
6
|
+
<div class="card-header">
|
7
|
+
<h5 class="card-title mb-0">
|
8
|
+
Keys
|
9
|
+
</h5>
|
10
|
+
</div>
|
11
|
+
<div class="card-body p-0">
|
12
|
+
<%= form_tag(keys_path, method: :get, class: 'p-4', enforce_utf8: false) do %>
|
13
|
+
<div class="input-group">
|
14
|
+
<%= text_field_tag :query, params[:query], class: 'form-control', placeholder: 'Search key(s)' %>
|
15
|
+
<div class="input-group-append">
|
16
|
+
<%= submit_tag 'Search', class: 'btn btn-primary', name: nil %>
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
<% end %>
|
20
|
+
<div class="table-responsive">
|
21
|
+
<table class="table mb-0">
|
22
|
+
<thead>
|
23
|
+
<tr>
|
24
|
+
<th>Name</th>
|
25
|
+
<th>Expiration Date</th>
|
26
|
+
<th>Size</th>
|
27
|
+
<th>Type</th>
|
28
|
+
<th>Options</th>
|
29
|
+
</tr>
|
30
|
+
</thead>
|
31
|
+
<tbody>
|
32
|
+
<% @keys.each do |key| %>
|
33
|
+
<tr>
|
34
|
+
<td><%= link_to (key[:key]).truncate(45), key_path(key: key[:key]), title: "Show #{key[:key]}" %></td>
|
35
|
+
<td><%= expire(key[:expire]) %></td>
|
36
|
+
<td><code><%= number_to_human_size(key[:memory]) %></code></td>
|
37
|
+
<td><kbd class="bg-dark"><%= key[:type] %></kbd></td>
|
38
|
+
<td>
|
39
|
+
<%= link_to 'Edit', edit_key_path(key: key[:key]), title: "Edit #{key[:key]}", class: 'btn btn-sm btn-primary ml-2' %>
|
40
|
+
<%= link_to 'Delete', destroy_key_path(key: key[:key]), method: :delete, data: {confirm: 'Are you sure ?'}, title: "Delete #{key[:key]}", class: 'btn btn-sm btn-danger ml-2' %>
|
41
|
+
</td>
|
42
|
+
</tr>
|
43
|
+
<% end %>
|
44
|
+
</tbody>
|
45
|
+
</table>
|
46
|
+
</div>
|
47
|
+
</div>
|
48
|
+
</div>
|
49
|
+
<div class="d-flex align-items-center justify-content-center mt-3">
|
50
|
+
<%= pagy_bootstrap_nav(@pagy).html_safe %>
|
51
|
+
</div>
|
52
|
+
</div>
|
53
|
+
</div>
|
54
|
+
</div>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<div class="container mt-4">
|
2
|
+
<div class="row">
|
3
|
+
<div class="col-12">
|
4
|
+
<label class="font-weight-normal">Key:</label>
|
5
|
+
<p class="font-weight-light">
|
6
|
+
<code><%= @key[:key] %></code>
|
7
|
+
</p>
|
8
|
+
<label class="font-weight-normal">Value:</label>
|
9
|
+
<p class="font-weight-light">
|
10
|
+
<code><%= @key[:node][:value] %></code>
|
11
|
+
</p>
|
12
|
+
<label class="font-weight-normal">Expires in:</label>
|
13
|
+
<p class="font-weight-light">
|
14
|
+
<%= expire(@key[:expire]) %>
|
15
|
+
</p>
|
16
|
+
<label class="font-weight-normal">Size:</label>
|
17
|
+
<p class="font-weight-light">
|
18
|
+
<code><%= number_to_human_size(@key[:memory]) %></code>
|
19
|
+
</p>
|
20
|
+
<label class="font-weight-normal">Type:</label>
|
21
|
+
<p class="font-weight-light">
|
22
|
+
<kbd class="bg-dark"><%= @key[:type] %></kbd>
|
23
|
+
</p>
|
24
|
+
<p class="font-weight-light">
|
25
|
+
<%= link_to 'Delete', destroy_key_path(key: @key[:key]), method: :delete, data: {confirm: 'Are you sure ?'}, title: "Delete #{@key}", class: 'btn btn-sm btn-danger w-100 mb-2' %>
|
26
|
+
<%= link_to 'Back', keys_path, title: 'View keys', class: 'btn btn-sm btn-primary w-100' %>
|
27
|
+
</p>
|
28
|
+
</div>
|
29
|
+
</div>
|
30
|
+
</div>
|
@@ -23,15 +23,25 @@
|
|
23
23
|
</li>
|
24
24
|
</ul>
|
25
25
|
<ul class="navbar-nav ml-auto">
|
26
|
+
<li class="nav-item">
|
27
|
+
<%= link_to 'Reset statistics',
|
28
|
+
reset_path,
|
29
|
+
title: 'Reset statistics',
|
30
|
+
method: :delete,
|
31
|
+
data: {
|
32
|
+
confirm: 'Are you sure you want to reset statistics ?'
|
33
|
+
},
|
34
|
+
class: 'btn btn-sm btn-info nav-link text-white mr-xs-0 mr-lg-2 mb-2 mb-lg-0' %>
|
35
|
+
</li>
|
26
36
|
<li class="nav-item">
|
27
37
|
<%= link_to 'Flush ALL',
|
28
|
-
|
38
|
+
flushall_path,
|
29
39
|
title: 'Flush ALL',
|
30
40
|
method: :delete,
|
31
41
|
data: {
|
32
42
|
confirm: 'Are you sure you want to flush all DB ?'
|
33
43
|
},
|
34
|
-
class: 'btn btn-sm btn-
|
44
|
+
class: 'btn btn-sm btn-dark nav-link text-white mr-xs-0 mr-lg-2 mb-2 mb-lg-0' %>
|
35
45
|
</li>
|
36
46
|
<li class="nav-item">
|
37
47
|
<%= link_to 'Flush DB',
|
data/bin/rails
CHANGED
data/config/routes.rb
CHANGED
@@ -7,10 +7,18 @@ RedisWebManager::Engine.routes.draw do
|
|
7
7
|
# Information
|
8
8
|
get :information, to: 'information#index'
|
9
9
|
|
10
|
+
# Keys
|
11
|
+
get 'keys' => 'keys#index'
|
12
|
+
get 'key' => 'keys#show'
|
13
|
+
get 'key/edit' => 'keys#edit', as: :edit_key
|
14
|
+
put 'keys' => 'keys#update', as: :update_key
|
15
|
+
delete 'keys' => 'keys#destroy', as: :destroy_key
|
16
|
+
|
10
17
|
# Clients
|
11
18
|
get :clients, to: 'clients#index'
|
12
19
|
|
13
20
|
# Actions
|
21
|
+
delete :reset, to: 'actions#reset'
|
14
22
|
delete :flushdb, to: 'actions#flushdb'
|
15
23
|
delete :flushall, to: 'actions#flushall'
|
16
24
|
|
data/lib/redis_web_manager.rb
CHANGED
@@ -10,8 +10,8 @@ require 'redis'
|
|
10
10
|
|
11
11
|
module RedisWebManager
|
12
12
|
mattr_accessor :redis, default: ::Redis.new
|
13
|
-
mattr_accessor :authenticate, default: nil
|
14
13
|
mattr_accessor :lifespan, default: 15.days
|
14
|
+
mattr_accessor :authenticate, default: nil
|
15
15
|
|
16
16
|
class << self
|
17
17
|
def configure
|
@@ -4,14 +4,30 @@ module RedisWebManager
|
|
4
4
|
class Data < Base
|
5
5
|
BASE = 'RedisWebManager'
|
6
6
|
|
7
|
+
def keys
|
8
|
+
data.map { |key| JSON.parse(redis.get(key), symbolize_names: true) }
|
9
|
+
end
|
10
|
+
|
7
11
|
def perform
|
8
12
|
now = Time.now.to_i
|
9
13
|
seconds = (now + lifespan.to_i) - now
|
10
14
|
redis.setex("#{BASE}_#{now}", seconds, serialize.to_json)
|
11
15
|
end
|
12
16
|
|
17
|
+
def flush
|
18
|
+
data.map { |key| redis.del(key) }
|
19
|
+
end
|
20
|
+
|
13
21
|
private
|
14
22
|
|
23
|
+
def data
|
24
|
+
@data ||= redis.scan_each(match: "#{BASE}_*").to_a
|
25
|
+
end
|
26
|
+
|
27
|
+
def lifespan
|
28
|
+
@lifespan ||= RedisWebManager.lifespan
|
29
|
+
end
|
30
|
+
|
15
31
|
def serialize
|
16
32
|
{
|
17
33
|
date: Time.now,
|
data/redis_web_manager.gemspec
CHANGED
@@ -10,11 +10,10 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.name = 'redis_web_manager'
|
11
11
|
spec.version = RedisWebManager::VERSION
|
12
12
|
|
13
|
-
spec.authors = ['Boris BRESCIANI', 'Benjamin DARCET', 'Olivier DUMAS'
|
13
|
+
spec.authors = ['Boris BRESCIANI', 'Benjamin DARCET', 'Olivier DUMAS']
|
14
14
|
spec.email = %w[boris2bresciani@gmail.com
|
15
15
|
b.darcet@gmail.com
|
16
|
-
dumas.olivier@outlook.fr
|
17
|
-
sylvain.kraisin@gmail.com]
|
16
|
+
dumas.olivier@outlook.fr]
|
18
17
|
|
19
18
|
spec.summary = 'Manage your Redis instance (See keys, memory used, connected client, etc...)'
|
20
19
|
spec.description = 'Manage your Redis instance (See keys, memory used, connected client, configuration, information)'
|
@@ -35,8 +34,11 @@ Gem::Specification.new do |spec|
|
|
35
34
|
spec.require_paths = ['lib']
|
36
35
|
spec.test_files = Dir['spec/**/*']
|
37
36
|
|
37
|
+
spec.add_development_dependency 'coveralls', '~> 0.8'
|
38
38
|
spec.add_development_dependency 'rspec-rails', '= 4.0.0.beta3'
|
39
|
+
spec.add_development_dependency 'simplecov', '~> 0.16'
|
39
40
|
|
41
|
+
spec.add_dependency 'pagy', '~> 3.7'
|
40
42
|
spec.add_dependency 'rails', '>= 5.2', '< 7'
|
41
43
|
spec.add_dependency 'redis', '~> 4.1.0'
|
42
|
-
end
|
44
|
+
end
|
@@ -5,9 +5,24 @@ require 'rails_helper'
|
|
5
5
|
RSpec.describe RedisWebManager::ActionsController, type: :controller do
|
6
6
|
routes { RedisWebManager::Engine.routes }
|
7
7
|
|
8
|
+
describe 'DELETE #reset' do
|
9
|
+
it 'returns a success response' do
|
10
|
+
delete :reset
|
11
|
+
expect(response).to be_redirect
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
8
15
|
describe 'DELETE #flushdb' do
|
16
|
+
it 'returns a success response' do
|
17
|
+
delete :flushdb
|
18
|
+
expect(response).to be_redirect
|
19
|
+
end
|
9
20
|
end
|
10
21
|
|
11
22
|
describe 'DELETE #flushall' do
|
23
|
+
it 'returns a success response' do
|
24
|
+
delete :flushall
|
25
|
+
expect(response).to be_redirect
|
26
|
+
end
|
12
27
|
end
|
13
|
-
end
|
28
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
RSpec.describe RedisWebManager::KeysController, type: :controller do
|
6
|
+
routes { RedisWebManager::Engine.routes }
|
7
|
+
let(:redis) do
|
8
|
+
::Redis.new
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'GET #index' do
|
12
|
+
it 'returns a success response' do
|
13
|
+
get :index
|
14
|
+
expect(response).to be_successful
|
15
|
+
get :index, params: { query: 'Search' }
|
16
|
+
expect(response).to be_successful
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'GET #show' do
|
21
|
+
it 'returns a success response' do
|
22
|
+
redis.set('test', 'test')
|
23
|
+
get :show, params: { key: 'test' }
|
24
|
+
expect(response).to be_successful
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'GET #edit' do
|
29
|
+
it 'returns a success response' do
|
30
|
+
redis.set('test', 'test')
|
31
|
+
get :edit, params: { key: 'test' }
|
32
|
+
expect(response).to be_successful
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'GET #update' do
|
37
|
+
it 'returns a success response' do
|
38
|
+
redis.set('test', 'test')
|
39
|
+
put :update, params: { old_name: 'test', new_name: 'testtest' }
|
40
|
+
expect(response).to be_redirect
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'GET #destroy' do
|
45
|
+
it 'returns a success response' do
|
46
|
+
redis.set('test', 'test')
|
47
|
+
delete :destroy, params: { key: 'test' }
|
48
|
+
expect(response).to be_redirect
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'Methods' do
|
53
|
+
it 'returns a hash value (get_value - string)' do
|
54
|
+
redis.set('test', 'test')
|
55
|
+
eql = {
|
56
|
+
value: 'test'
|
57
|
+
}
|
58
|
+
expect(controller.send(:get_value, 'test')).to eql(eql)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'returns a hash value (get_value - hgetall)' do
|
62
|
+
eql = {
|
63
|
+
value: {
|
64
|
+
'name' => {
|
65
|
+
type: 'string',
|
66
|
+
value: 'hgetall'
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
70
|
+
redis.hset('hgetall', 'name', 'hgetall')
|
71
|
+
expect(controller.send(:get_value, 'hgetall')).to eql(eql)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'returns a hash value (get_value - lrange)' do
|
75
|
+
redis.lpush('lrange', '1')
|
76
|
+
redis.lpush('lrange', '2')
|
77
|
+
eql = {
|
78
|
+
length: 2,
|
79
|
+
values: [
|
80
|
+
{
|
81
|
+
index: 0,
|
82
|
+
type: 'json',
|
83
|
+
value: 2
|
84
|
+
},
|
85
|
+
{
|
86
|
+
index: 1,
|
87
|
+
type: 'json',
|
88
|
+
value: 1
|
89
|
+
}
|
90
|
+
]
|
91
|
+
}
|
92
|
+
expect(controller.send(:get_value, 'lrange')).to eql(eql)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'returns a hash value (get_value - set)' do
|
96
|
+
redis.sadd('smembers', 'smembers')
|
97
|
+
eql = {
|
98
|
+
values: [{ type: 'string', value: 'smembers' }]
|
99
|
+
}
|
100
|
+
expect(controller.send(:get_value, 'smembers')).to eql(eql)
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'returns a hash value (get_value - zset)' do
|
104
|
+
redis.zadd('zrange', 10, '1')
|
105
|
+
redis.zadd('zrange', 20, '2')
|
106
|
+
redis.zadd('zrange', 30, '3')
|
107
|
+
eql = {
|
108
|
+
values: [
|
109
|
+
{
|
110
|
+
score: 10.0,
|
111
|
+
type: 'json',
|
112
|
+
value: 1
|
113
|
+
},
|
114
|
+
{
|
115
|
+
score: 20.0,
|
116
|
+
type: 'json',
|
117
|
+
value: 2
|
118
|
+
},
|
119
|
+
{
|
120
|
+
score: 30.0,
|
121
|
+
type: 'json',
|
122
|
+
value: 3
|
123
|
+
}
|
124
|
+
]
|
125
|
+
}
|
126
|
+
expect(controller.send(:get_value, 'zrange')).to eql(eql)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'returns a hash value (get_value - not found)' do
|
130
|
+
redis.zadd('zrange', 10, '1')
|
131
|
+
redis.zadd('zrange', 20, '2')
|
132
|
+
redis.zadd('zrange', 30, '3')
|
133
|
+
eql = {
|
134
|
+
value: 'Not found'
|
135
|
+
}
|
136
|
+
expect(controller.send(:get_value, 'testtesttesttesttest')).to eql(eql)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|