elasticshell 0.0.2 → 0.0.4
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.
- data/README.rdoc +119 -55
- data/VERSION +1 -1
- data/bin/es +0 -2
- data/lib/elasticshell.rb +30 -25
- data/lib/elasticshell/client.rb +34 -13
- data/lib/elasticshell/command.rb +14 -170
- data/lib/elasticshell/commands/blank.rb +14 -0
- data/lib/elasticshell/commands/cd.rb +27 -0
- data/lib/elasticshell/commands/connect.rb +31 -0
- data/lib/elasticshell/commands/df.rb +23 -0
- data/lib/elasticshell/commands/help.rb +77 -0
- data/lib/elasticshell/commands/ls.rb +66 -0
- data/lib/elasticshell/commands/pretty.rb +21 -0
- data/lib/elasticshell/commands/pwd.rb +17 -0
- data/lib/elasticshell/commands/request.rb +81 -0
- data/lib/elasticshell/commands/request_parser.rb +77 -0
- data/lib/elasticshell/commands/set_verb.rb +23 -0
- data/lib/elasticshell/commands/unknown.rb +17 -0
- data/lib/elasticshell/scopes.rb +81 -50
- data/lib/elasticshell/scopes/cluster.rb +8 -16
- data/lib/elasticshell/scopes/global.rb +22 -23
- data/lib/elasticshell/scopes/index.rb +35 -29
- data/lib/elasticshell/scopes/mapping.rb +8 -28
- data/lib/elasticshell/scopes/nodes.rb +6 -15
- data/lib/elasticshell/shell.rb +155 -93
- data/lib/elasticshell/utils.rb +10 -0
- data/lib/elasticshell/{error.rb → utils/error.rb} +1 -0
- data/lib/elasticshell/utils/has_name.rb +14 -0
- data/lib/elasticshell/utils/has_verb.rb +15 -0
- data/lib/elasticshell/{log.rb → utils/log.rb} +1 -1
- data/lib/elasticshell/utils/recognizes_verb.rb +25 -0
- data/spec/elasticshell/client_spec.rb +55 -0
- data/spec/elasticshell/commands/blank_spec.rb +14 -0
- data/spec/elasticshell/commands/cd_spec.rb +23 -0
- data/spec/elasticshell/commands/connect_spec.rb +21 -0
- data/spec/elasticshell/commands/df_spec.rb +18 -0
- data/spec/elasticshell/commands/help_spec.rb +21 -0
- data/spec/elasticshell/commands/ls_spec.rb +24 -0
- data/spec/elasticshell/commands/pretty_spec.rb +19 -0
- data/spec/elasticshell/commands/pwd_spec.rb +14 -0
- data/spec/elasticshell/commands/request_parser_spec.rb +4 -0
- data/spec/elasticshell/commands/request_spec.rb +60 -0
- data/spec/elasticshell/commands/set_verb_spec.rb +14 -0
- data/spec/elasticshell/scopes_spec.rb +79 -0
- data/spec/elasticshell/shell_spec.rb +19 -0
- data/spec/elasticshell/utils/has_name_spec.rb +15 -0
- data/spec/elasticshell/utils/has_verb_spec.rb +24 -0
- data/spec/elasticshell/utils/recognizes_verb_spec.rb +23 -0
- data/spec/spec_helper.rb +4 -5
- data/spec/support/data.yml +45 -0
- data/spec/support/fake_output.rb +27 -0
- metadata +73 -4
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'elasticshell/utils/recognizes_verb'
|
2
|
+
|
3
|
+
module Elasticshell
|
4
|
+
module Commands
|
5
|
+
class SetVerb < Command
|
6
|
+
|
7
|
+
include RecognizesVerb
|
8
|
+
extend RecognizesVerb
|
9
|
+
|
10
|
+
def self.matches? input
|
11
|
+
is_http_verb?(input)
|
12
|
+
end
|
13
|
+
|
14
|
+
def evaluate!
|
15
|
+
v = canonicalize_verb(input)
|
16
|
+
shell.verb = v
|
17
|
+
shell.scope.verb = v
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Elasticshell
|
2
|
+
module Commands
|
3
|
+
class Unknown < Command
|
4
|
+
|
5
|
+
def self.matches? input
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
def evaluate!
|
10
|
+
raise ArgumentError.new("Invalid command: '#{shell.input}' for scope '#{shell.scope.path}'. Try typing 'help' for a list of available commands.")
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
data/lib/elasticshell/scopes.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'elasticshell/error'
|
2
1
|
require 'uri'
|
3
2
|
|
4
3
|
module Elasticshell
|
@@ -52,12 +51,19 @@ module Elasticshell
|
|
52
51
|
|
53
52
|
class Scope
|
54
53
|
|
55
|
-
|
54
|
+
include Elasticshell::HasVerb
|
56
55
|
|
56
|
+
attr_accessor :path, :client, :last_refresh_at, :scopes
|
57
|
+
|
58
|
+
def self.requests
|
59
|
+
@requests ||= {}
|
60
|
+
end
|
61
|
+
|
57
62
|
def initialize path, options
|
58
|
-
self.
|
59
|
-
self.
|
60
|
-
self.
|
63
|
+
self.verb = options.delete(:verb)
|
64
|
+
self.path = path
|
65
|
+
self.client = options[:client]
|
66
|
+
self.scopes = initial_scopes
|
61
67
|
end
|
62
68
|
|
63
69
|
def to_s
|
@@ -65,89 +71,114 @@ module Elasticshell
|
|
65
71
|
end
|
66
72
|
|
67
73
|
def completion_proc
|
68
|
-
Proc.new do |prefix|
|
69
|
-
refresh
|
74
|
+
Proc.new do |shell, prefix|
|
75
|
+
refresh if client.connected?
|
70
76
|
case
|
71
77
|
when Readline.line_buffer =~ /^\s*cd\s+\S*$/
|
72
|
-
|
73
|
-
|
74
|
-
|
78
|
+
# User has typed 'cd' so we should be completing scopes only
|
79
|
+
completing_scope_path, prefix_within_completing_scope = completing_scope_path_and_prefix(prefix)
|
80
|
+
completing_scope = shell.scope_from_path(File.expand_path(completing_scope_path, shell.scope.path))
|
81
|
+
completing_scope.refresh if client.connected?
|
82
|
+
completing_scope.scopes_matching(prefix_within_completing_scope)
|
75
83
|
when Readline.line_buffer =~ /^\s*\S*$/
|
76
|
-
|
77
|
-
|
78
|
-
|
84
|
+
# User has started but not completed the first word in the
|
85
|
+
# line so it must be a request available in the current
|
86
|
+
# scope.
|
87
|
+
requests_matching(prefix)
|
88
|
+
when Readline.line_buffer =~ />.*$/
|
89
|
+
# User has started to complete the name of a filesystem path
|
90
|
+
# to redirect output to.
|
91
|
+
Dir[prefix + '*']
|
79
92
|
else
|
93
|
+
# The user has finished the first word on the line so we try
|
94
|
+
# to match to a filesystem path.
|
80
95
|
Dir[prefix + '*']
|
81
96
|
end
|
82
97
|
end
|
83
98
|
end
|
84
99
|
|
85
|
-
def
|
86
|
-
|
87
|
-
commands.keys.sort
|
100
|
+
def requests
|
101
|
+
self.class.requests[verb] || {}
|
88
102
|
end
|
89
103
|
|
90
|
-
def
|
91
|
-
|
104
|
+
def request_names
|
105
|
+
requests.keys
|
92
106
|
end
|
93
107
|
|
108
|
+
def requests_matching prefix
|
109
|
+
if prefix.empty?
|
110
|
+
request_names.sort
|
111
|
+
else
|
112
|
+
request_names.find_all { |name| name[0...prefix.length] == prefix }.sort
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
94
116
|
def refresh
|
95
117
|
refresh! unless refreshed?
|
96
118
|
end
|
97
119
|
|
98
120
|
def refresh!
|
99
121
|
reset!
|
100
|
-
|
122
|
+
fetch_scopes
|
101
123
|
self.last_refresh_at = Time.now
|
102
124
|
true
|
103
125
|
end
|
104
126
|
|
105
|
-
def
|
127
|
+
def fetch_scopes
|
106
128
|
end
|
107
129
|
|
108
|
-
def
|
130
|
+
def initial_scopes
|
109
131
|
[]
|
110
132
|
end
|
111
133
|
|
134
|
+
def completing_scope_path_and_prefix prefix
|
135
|
+
if prefix =~ %r!^/!
|
136
|
+
if prefix =~ %r!/$!
|
137
|
+
index = -1
|
138
|
+
prefix_within_completing_scope = ''
|
139
|
+
else
|
140
|
+
index = -2
|
141
|
+
end
|
142
|
+
completing_scope_path = prefix.split('/')[0..index].join('/')
|
143
|
+
completing_scope_path = '/' if completing_scope_path.empty?
|
144
|
+
prefix_within_completing_scope ||= (prefix.split('/').last || '')
|
145
|
+
else
|
146
|
+
if prefix =~ %r!/$!
|
147
|
+
index = -1
|
148
|
+
prefix_within_completing_scope = ''
|
149
|
+
else
|
150
|
+
index = -2
|
151
|
+
end
|
152
|
+
completing_scope_path = File.join(self.path, prefix.split('/')[0..index].join('/'))
|
153
|
+
completing_scope_path = self.path if completing_scope_path.empty?
|
154
|
+
prefix_within_completing_scope ||= (prefix.split('/').last || '')
|
155
|
+
end
|
156
|
+
[completing_scope_path, prefix_within_completing_scope]
|
157
|
+
end
|
158
|
+
|
159
|
+
def scopes_matching prefix
|
160
|
+
scopes.find_all do |scope|
|
161
|
+
prefix.empty? ? true : scope[0...prefix.length] == prefix
|
162
|
+
end.map do |scope|
|
163
|
+
scope =~ %r!/$! ? scope : scope + '/'
|
164
|
+
end.sort.map do |scope|
|
165
|
+
File.join(path, scope)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
112
169
|
def reset!
|
113
|
-
self.
|
170
|
+
self.scopes = initial_scopes
|
114
171
|
true
|
115
172
|
end
|
116
173
|
|
117
174
|
def refreshed?
|
118
|
-
self.last_refresh_at
|
175
|
+
! self.last_refresh_at.nil?
|
119
176
|
end
|
120
177
|
|
121
178
|
def exists?
|
122
179
|
false
|
123
180
|
end
|
124
|
-
|
125
|
-
def command? command
|
126
|
-
command_names.any? do |command_name|
|
127
|
-
command[0...command_name.length] == command_name
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def execute command, shell
|
132
|
-
if command_names.include?(command)
|
133
|
-
raise NotImplementedError.new("Have not yet implemented '#{command}' for scope '#{path}'.")
|
134
|
-
else
|
135
|
-
raise ArgumentError.new("No such command '#{command}' in scope '#{path}'.")
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
def help
|
140
|
-
[].tap do |msg|
|
141
|
-
msg << "Commands specific to the scope '#{path}':"
|
142
|
-
msg << ''
|
143
|
-
commands.each_pair do |command_name, description|
|
144
|
-
msg << ' ' + command_name
|
145
|
-
msg << (' ' + description)
|
146
|
-
msg << ''
|
147
|
-
end
|
148
|
-
end.join("\n")
|
149
|
-
end
|
150
|
-
|
181
|
+
|
151
182
|
end
|
152
183
|
|
153
184
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'elasticshell/scopes'
|
2
|
-
|
3
1
|
module Elasticshell
|
4
2
|
|
5
3
|
module Scopes
|
@@ -10,26 +8,20 @@ module Elasticshell
|
|
10
8
|
super("/_cluster", options)
|
11
9
|
end
|
12
10
|
|
13
|
-
def
|
14
|
-
{
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
def self.requests
|
12
|
+
@requests = {
|
13
|
+
"GET" =>
|
14
|
+
{
|
15
|
+
'health' => "Retreive the health of the cluster.",
|
16
|
+
'state' => "Retreive the state of the cluster.",
|
17
|
+
'settings'=> "Retreive the settings for the cluster.",
|
18
|
+
}
|
18
19
|
}
|
19
20
|
end
|
20
21
|
|
21
22
|
def exists?
|
22
23
|
true
|
23
24
|
end
|
24
|
-
|
25
|
-
def execute command, shell
|
26
|
-
case
|
27
|
-
when command?(command)
|
28
|
-
shell.request(:get, :index => '_cluster')
|
29
|
-
else
|
30
|
-
super(command, shell)
|
31
|
-
end
|
32
|
-
end
|
33
25
|
|
34
26
|
end
|
35
27
|
end
|
@@ -1,27 +1,41 @@
|
|
1
|
-
require 'elasticshell/scopes'
|
2
|
-
|
3
1
|
module Elasticshell
|
4
2
|
|
5
3
|
module Scopes
|
6
4
|
|
7
5
|
class Global < Scope
|
8
6
|
|
7
|
+
attr_reader :indices
|
8
|
+
|
9
9
|
def initialize options={}
|
10
|
+
@indices = []
|
10
11
|
super("/", options)
|
11
12
|
end
|
12
13
|
|
13
|
-
def
|
14
|
-
{
|
15
|
-
|
14
|
+
def self.requests
|
15
|
+
@requests ||= {
|
16
|
+
"GET" => {
|
17
|
+
'_status' => "Retreive the status of all indices in the cluster."
|
18
|
+
}
|
16
19
|
}
|
17
20
|
end
|
18
21
|
|
19
|
-
def
|
22
|
+
def initial_scopes
|
20
23
|
['_cluster', '_nodes']
|
21
24
|
end
|
22
25
|
|
23
|
-
def
|
24
|
-
|
26
|
+
def status
|
27
|
+
@status ||= client.safely(:get, {:index => '_status'}, :return => {"indices" => {}}, :log => false)
|
28
|
+
end
|
29
|
+
|
30
|
+
def reset!
|
31
|
+
@indices = []
|
32
|
+
@status = nil
|
33
|
+
super()
|
34
|
+
end
|
35
|
+
|
36
|
+
def fetch_scopes
|
37
|
+
@indices = status["indices"].keys
|
38
|
+
self.scopes += @indices
|
25
39
|
end
|
26
40
|
|
27
41
|
def index name, options={}
|
@@ -31,21 +45,6 @@ module Elasticshell
|
|
31
45
|
def exists?
|
32
46
|
true
|
33
47
|
end
|
34
|
-
|
35
|
-
def execute command, shell
|
36
|
-
case
|
37
|
-
when command =~ /^_cluster/
|
38
|
-
shell.scope = Scopes.cluster(:client => client)
|
39
|
-
when command =~ /^_nodes/
|
40
|
-
shell.scope = Scopes.nodes(:client => client)
|
41
|
-
when command?(command)
|
42
|
-
shell.request(:get)
|
43
|
-
when index_names.include?(command)
|
44
|
-
shell.scope = index(command)
|
45
|
-
else
|
46
|
-
super(command, shell)
|
47
|
-
end
|
48
|
-
end
|
49
48
|
|
50
49
|
end
|
51
50
|
end
|
@@ -1,30 +1,27 @@
|
|
1
|
-
require 'elasticshell/scopes'
|
2
|
-
|
3
1
|
module Elasticshell
|
4
2
|
|
5
3
|
module Scopes
|
6
4
|
|
7
5
|
class Index < Scope
|
8
6
|
|
9
|
-
|
7
|
+
include HasName
|
8
|
+
|
9
|
+
attr_reader :mappings
|
10
10
|
|
11
11
|
def initialize name, options={}
|
12
12
|
self.name = name
|
13
|
+
@mappings = []
|
13
14
|
super("/#{self.name}", options)
|
14
15
|
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
"_aliases" => "Find the aliases for this index.",
|
25
|
-
"_status" => "Retrieve the status of this index.",
|
26
|
-
"_stats" => "Retrieve usage stats for this index.",
|
27
|
-
"_search" => "Search records within this index.",
|
17
|
+
def self.requests
|
18
|
+
@requests ||= {
|
19
|
+
"GET" => {
|
20
|
+
"_aliases" => "Find the aliases for this index.",
|
21
|
+
"_status" => "Retrieve the status of this index.",
|
22
|
+
"_stats" => "Retrieve usage stats for this index.",
|
23
|
+
"_search" => "Search records within this index.",
|
24
|
+
}
|
28
25
|
}
|
29
26
|
end
|
30
27
|
|
@@ -32,28 +29,37 @@ module Elasticshell
|
|
32
29
|
@global ||= Scopes.global(:client => client)
|
33
30
|
end
|
34
31
|
|
32
|
+
def status
|
33
|
+
@status ||= client.safely(:get, {:index => name, :op => '_status'}, :return => {"indices" => {name => {}}}, :log => false)
|
34
|
+
end
|
35
|
+
|
36
|
+
def reset!
|
37
|
+
@status = nil
|
38
|
+
@mappings = []
|
39
|
+
super()
|
40
|
+
end
|
41
|
+
|
35
42
|
def exists?
|
43
|
+
return false unless client.connected?
|
36
44
|
global.refresh
|
37
|
-
global.
|
45
|
+
global.scopes.include?(name)
|
38
46
|
end
|
39
47
|
|
40
|
-
def
|
41
|
-
|
48
|
+
def multi?
|
49
|
+
name.include?(',')
|
42
50
|
end
|
43
51
|
|
44
|
-
def
|
45
|
-
|
52
|
+
def single?
|
53
|
+
! multi?
|
54
|
+
end
|
55
|
+
|
56
|
+
def fetch_scopes
|
57
|
+
@mappings = (client.safely(:get, {:index => name, :op => '_mapping'}, :return => { name => {}}, :log => false)[name] || {}).keys
|
58
|
+
self.scopes += @mappings
|
46
59
|
end
|
47
60
|
|
48
|
-
def
|
49
|
-
|
50
|
-
when command?(command)
|
51
|
-
shell.request(:get, :index => name)
|
52
|
-
when mapping_names.include?(command)
|
53
|
-
shell.scope = mapping(command)
|
54
|
-
else
|
55
|
-
super(command, shell)
|
56
|
-
end
|
61
|
+
def mapping mapping_name, options={}
|
62
|
+
Scopes.mapping(self.name, mapping_name, options.merge(:client => client))
|
57
63
|
end
|
58
64
|
|
59
65
|
end
|
@@ -1,12 +1,10 @@
|
|
1
|
-
require 'elasticshell/scopes'
|
2
|
-
|
3
1
|
module Elasticshell
|
4
2
|
|
5
3
|
module Scopes
|
6
4
|
|
7
5
|
class Mapping < Scope
|
8
6
|
|
9
|
-
|
7
|
+
include HasName
|
10
8
|
|
11
9
|
attr_accessor :index
|
12
10
|
|
@@ -16,38 +14,20 @@ module Elasticshell
|
|
16
14
|
super("/#{index.name}/#{self.name}", options)
|
17
15
|
end
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
def commands
|
26
|
-
{
|
27
|
-
"_search" => "Search records within this mapping.",
|
28
|
-
"_mapping" => "Retrieve the mapping settings for this mapping.",
|
17
|
+
def self.requests
|
18
|
+
@requests ||= {
|
19
|
+
"GET" => {
|
20
|
+
"_search" => "Search records within this mapping.",
|
21
|
+
"_mapping" => "Retrieve the mapping settings for this mapping.",
|
22
|
+
}
|
29
23
|
}
|
30
24
|
end
|
31
25
|
|
32
26
|
def exists?
|
33
27
|
index.refresh
|
34
|
-
index.
|
28
|
+
index.scopes.include?(name)
|
35
29
|
end
|
36
30
|
|
37
|
-
def command? command
|
38
|
-
true
|
39
|
-
end
|
40
|
-
|
41
|
-
def execute command, shell
|
42
|
-
case
|
43
|
-
when command?(command)
|
44
|
-
shell.request(:get, :index => index.name, :type => name)
|
45
|
-
else
|
46
|
-
record = shell.request(:get, :index => index.name, :type => name)
|
47
|
-
shell.print(record) if record
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
31
|
end
|
52
32
|
end
|
53
33
|
end
|