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
data/README.rdoc
CHANGED
@@ -26,12 +26,12 @@ How about
|
|
26
26
|
|
27
27
|
== Installation
|
28
28
|
|
29
|
-
|
29
|
+
Install the gem:
|
30
30
|
|
31
31
|
$ sudo gem install elasticshell
|
32
32
|
|
33
|
-
|
34
|
-
|
33
|
+
which installs a program 'es' that you can run from the command line
|
34
|
+
to start Elasticshell. Try
|
35
35
|
|
36
36
|
$ es --help
|
37
37
|
|
@@ -53,57 +53,115 @@ Within Elasticshell, there are three variables whose values affect
|
|
53
53
|
behavior. These variables are reflected in the default prompt, for
|
54
54
|
example:
|
55
55
|
|
56
|
-
GET /my_index/my_type
|
56
|
+
GET /my_index/my_type$
|
57
57
|
|
58
58
|
This prompt tells us three things:
|
59
59
|
|
60
60
|
1. The default HTTP verb we're using for requests is +GET+.
|
61
61
|
|
62
|
-
2. The default API "scope" we're in is <tt>/my_index/my_type</tt>.
|
62
|
+
2. The default API "scope" we're in is <tt>/my_index/my_type</tt>. If the shell is connected to an Elasticsearch server and the scope exists, it will be colored green. Otherwise it's yellow.
|
63
63
|
|
64
|
-
3. Elasticshell will print raw responses from the database -- this is the <tt
|
64
|
+
3. Elasticshell will print raw responses from the database -- this is the <tt>$</tt> at the end of the prompt. If we were in pretty-print mode, this would become a <tt>$$</tt>.
|
65
65
|
|
66
|
-
===
|
66
|
+
=== Connecting to the Database
|
67
|
+
|
68
|
+
Elasticshell will try to connect to the Elasticsearch hosts passed
|
69
|
+
with the <tt>--servers</tt> option during startup. At any other time,
|
70
|
+
you can connect to servers by issuing the +connect+ command:
|
71
|
+
|
72
|
+
GET /$ connect http://192.168.1.10:9200 http://192.168.1.11:9200 http://192.168.1.12:9200 http://192.168.1.13:9200
|
73
|
+
|
74
|
+
=== Understanding Scope
|
75
|
+
|
76
|
+
Scopes are defined by the Elasticsearch REST API. Some scopes like
|
77
|
+
<tt>/_cluster</tt> or <tt>/nodes</tt> are static and present for all
|
78
|
+
Elasticsearch clusters. Other scopes like <tt>/my_index/my_type</tt>
|
79
|
+
depend upon the particular cluster.
|
67
80
|
|
68
81
|
Use the +cd+ built-in to move between scopes:
|
69
82
|
|
70
|
-
GET
|
71
|
-
GET /
|
72
|
-
GET /
|
73
|
-
GET /
|
83
|
+
GET /$ cd /blog/comments
|
84
|
+
GET /blog/comments$ cd ..
|
85
|
+
GET /blog$ cd /blog/entries
|
86
|
+
GET /blog/entries$ cd
|
87
|
+
GET /$
|
88
|
+
|
89
|
+
==== Different kinds of scopes
|
90
|
+
|
91
|
+
The +ls+ command will show the contents of a given scope:
|
92
|
+
|
93
|
+
GET /$ ls
|
94
|
+
blog _cluster _nodes _status
|
95
|
+
|
96
|
+
but the +ll+ command gives more output:
|
97
|
+
|
98
|
+
GET /$ ll
|
99
|
+
i 1/1/0 5 3.3kb blog
|
100
|
+
s _cluster
|
101
|
+
s _nodes
|
102
|
+
- _status
|
74
103
|
|
75
|
-
|
76
|
-
|
104
|
+
Here you see that +blog+
|
105
|
+
|
106
|
+
- is an index (the +i+ in the first column)
|
107
|
+
- has 1 total shard, 1 successful shard, and 0 failed shards
|
108
|
+
- has 5 documents
|
109
|
+
- occupies 3.3kb of space on disk
|
110
|
+
|
111
|
+
And, because of the +s+ in the first-column, +_cluster+ and +_nodes+
|
112
|
+
are scopes -- you can +cd+ into them.
|
113
|
+
|
114
|
+
Finally, +_status+ is a request, you can't +cd+ into it, but you can
|
115
|
+
issue it.
|
116
|
+
|
117
|
+
If you were to first +cd+ into the index and run +ll+ you'll see
|
118
|
+
different output:
|
119
|
+
|
120
|
+
GET /$ cd /blog/
|
121
|
+
GET /blog$ ll
|
122
|
+
m comments
|
123
|
+
m entries
|
124
|
+
- _aliases
|
125
|
+
- _search
|
126
|
+
- _stats
|
127
|
+
- _status
|
128
|
+
|
129
|
+
+_aliases+ and so on are just more requests you can make but
|
130
|
+
+comments+ and +entries+ are mappings (they have an +m+ in the
|
131
|
+
first-column).
|
77
132
|
|
78
133
|
=== Changing HTTP Verb
|
79
134
|
|
80
135
|
You can change Elasticsearch's default HTTP verb by giving it one.
|
81
136
|
Here's the same thing in two steps:
|
82
137
|
|
83
|
-
GET
|
84
|
-
PUT
|
138
|
+
GET /$ PUT
|
139
|
+
PUT /$ /my_new_index
|
140
|
+
|
141
|
+
You can also do this on a per-request basis
|
85
142
|
|
86
|
-
|
87
|
-
|
143
|
+
GET /$ PUT /my_new_index
|
144
|
+
GET /$
|
88
145
|
|
89
146
|
=== Changing Prettiness
|
90
147
|
|
91
148
|
Typing +pretty+ at any time will toggle Elasticsearch's
|
92
149
|
pretty-printing format on or off.
|
93
150
|
|
94
|
-
GET
|
95
|
-
GET
|
151
|
+
GET /$ pretty
|
152
|
+
GET /$$
|
96
153
|
|
97
|
-
The <tt>$</tt>-sign means it's pretty...
|
154
|
+
The extra <tt>$</tt>-sign means it's pretty...
|
98
155
|
|
99
|
-
|
156
|
+
== Making Requests
|
100
157
|
|
101
|
-
|
102
|
-
|
158
|
+
Scopes are fine for organizing the API but to get anything done you'll
|
159
|
+
have to send a request.
|
103
160
|
|
104
|
-
|
161
|
+
=== Named requests
|
105
162
|
|
106
|
-
Each scope has different
|
163
|
+
Each scope has different fixed, named requests, as per the
|
164
|
+
{Elasticsearch API
|
107
165
|
documentation}[http://www.elasticsearch.org/guide/reference/api/].
|
108
166
|
Within a scope, tab-complete on the first word to see a list of
|
109
167
|
possible commands. Hit enter after a command to see output from
|
@@ -111,28 +169,32 @@ Elasticsearch.
|
|
111
169
|
|
112
170
|
Here's a command to get the status for the cluster:
|
113
171
|
|
114
|
-
GET
|
172
|
+
GET /$ _status
|
115
173
|
|
116
174
|
Here's a command to get the health of the cluster:
|
117
175
|
|
118
|
-
GET
|
119
|
-
GET /_cluster
|
176
|
+
GET /$ cd _cluster
|
177
|
+
GET /_cluster$ health
|
178
|
+
|
179
|
+
which you could also have issued like this
|
180
|
+
|
181
|
+
GET /$ _cluster/health
|
120
182
|
|
121
|
-
|
183
|
+
=== Using query strings
|
122
184
|
|
123
185
|
Commands will also accept a query string, as in this example of a
|
124
186
|
search through +my_index+:
|
125
187
|
|
126
|
-
GET /my_index
|
188
|
+
GET /my_index$ _search?q=foo+AND+bar
|
127
189
|
|
128
|
-
|
190
|
+
=== Using a body
|
129
191
|
|
130
|
-
In
|
192
|
+
In the above example the query <tt>foo AND bar</tt> was passed via the
|
131
193
|
query string part of a URL. Passing a more complex query requires we
|
132
194
|
put the query in the body of the request. If you're willing to forego
|
133
195
|
using spaces you can do this right on the same line:
|
134
196
|
|
135
|
-
GET /my_index
|
197
|
+
GET /my_index$ _search {"query":{"query_string":{"query":"foo"}}}
|
136
198
|
|
137
199
|
But if you want more expressiveness you can either name a file (with
|
138
200
|
tab-completion) that contains the body you want:
|
@@ -148,12 +210,12 @@ tab-completion) that contains the body you want:
|
|
148
210
|
|
149
211
|
followed by
|
150
212
|
|
151
|
-
GET /my_index
|
213
|
+
GET /my_index$ _search /tmp/query.json
|
152
214
|
|
153
215
|
Or you can do +cat+-style, pasting the query into the shell, by using
|
154
216
|
the <tt>-</tt> character:
|
155
217
|
|
156
|
-
GET /my_index
|
218
|
+
GET /my_index$ _search -
|
157
219
|
{
|
158
220
|
"query": {
|
159
221
|
"query_string: {
|
@@ -165,38 +227,40 @@ the <tt>-</tt> character:
|
|
165
227
|
Don't forget to use <tt>Ctrl-D</tt> to send an +EOF+ to flush the
|
166
228
|
input of the query.
|
167
229
|
|
168
|
-
|
230
|
+
=== Redirecting output
|
169
231
|
|
170
|
-
You can
|
171
|
-
the command with a leading slash:
|
232
|
+
You can redirect the output from a request in a variety of ways.
|
172
233
|
|
173
|
-
|
234
|
+
Most simply is to redirect to a file:
|
174
235
|
|
175
|
-
|
176
|
-
you send the request to. Here's how to create an index using a +PUT+
|
177
|
-
request:
|
236
|
+
GET /my_index$ _search /tmp/query_with_lots_of_output.json > /data/output_file.json
|
178
237
|
|
179
|
-
|
238
|
+
Or you can try sending it to Ruby itself:
|
180
239
|
|
181
|
-
|
182
|
-
one. Here's the same thing in two steps:
|
240
|
+
GET /my_index$ _search /tmp/query_that_needs_filtering.json | puts response["hits"]["hits"].first["body"]
|
183
241
|
|
184
|
-
|
185
|
-
|
242
|
+
Everything to the right of the +|+ is executing within a Ruby process
|
243
|
+
that has the +response+ and +request+ variables in scope. You can be
|
244
|
+
even more free by just piping without any Ruby code, which will leave
|
245
|
+
you in a Ruby (Pry) shell with the same binding.
|
186
246
|
|
187
|
-
|
188
|
-
|
247
|
+
GET /my_index$ _search /tmp/query_that_needs_interaction.json |
|
248
|
+
>> response
|
249
|
+
=> {"took"=>1, "timed_out"=>false, ... }
|
250
|
+
>> request
|
251
|
+
=> {:verb=>"GET", :path=>"/_search", :query_options=>{}, :body=>""}
|
189
252
|
|
190
|
-
===
|
253
|
+
=== Requests from the command line
|
191
254
|
|
192
255
|
Instead of running Elasticshell interactively, you can exit after
|
193
|
-
running only a single command by
|
194
|
-
|
256
|
+
running only a single command by feeding the request path directly to
|
257
|
+
the +es+ script. For example
|
195
258
|
|
196
|
-
$ es
|
259
|
+
$ es /_cluster/health
|
260
|
+
$ es --scope=/_cluster health
|
261
|
+
$ es --verb=GET /_cluster/health
|
197
262
|
|
198
|
-
|
199
|
-
combined with the <tt>--pretty</tt> option for readability.
|
263
|
+
all work like you think they do.
|
200
264
|
|
201
265
|
The <tt>--only</tt> option can also be passed a <tt>.</tt>-separated
|
202
266
|
hierarchical list of keys to slice into the resulting object. This is
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.4
|
data/bin/es
CHANGED
data/lib/elasticshell.rb
CHANGED
@@ -2,58 +2,63 @@ require 'rubygems'
|
|
2
2
|
require 'json'
|
3
3
|
require 'configliere'
|
4
4
|
|
5
|
-
require 'elasticshell/
|
6
|
-
require 'elasticshell/scopes'
|
7
|
-
require 'elasticshell/client'
|
5
|
+
require 'elasticshell/utils'
|
8
6
|
|
9
7
|
Settings.use(:commandline)
|
10
8
|
|
11
|
-
Settings.define(:servers, :description => "A comma-separated list of Elasticsearch servers to connect to.", :type => Array, :default =>
|
9
|
+
Settings.define(:servers, :description => "A comma-separated list of Elasticsearch servers to connect to.", :type => Array, :default => 'http://localhost:9200')
|
12
10
|
Settings.define(:only, :description => "A dot-separated hierarchical key to extract from the output scope.")
|
13
11
|
Settings.define(:pretty, :description => "Pretty-print all output. ", :default => false, :type => :boolean)
|
14
12
|
Settings.define(:verb, :description => "Set the default HTTP verb. ", :default => "GET")
|
15
13
|
Settings.define(:version, :description => "Print Elasticshell version and exit. ", :default => false, :type => :boolean)
|
14
|
+
Settings.define(:scope, :description => "The default scope to start the shell in.", :default => "/")
|
16
15
|
Settings.description = <<-DESC
|
17
16
|
Elasticshell is a command-line shell for interacting with an
|
18
17
|
Elasticsearch database. It has the following start-up options.
|
19
18
|
DESC
|
20
19
|
|
21
20
|
def Settings.usage
|
22
|
-
"usage: #{File.basename($0)} [OPTIONS] [
|
21
|
+
"usage: #{File.basename($0)} [OPTIONS] [REQUEST]"
|
23
22
|
end
|
24
23
|
Settings.resolve!
|
25
24
|
|
26
25
|
module Elasticshell
|
27
26
|
|
27
|
+
autoload :Client, 'elasticshell/client'
|
28
|
+
autoload :Shell, 'elasticshell/shell'
|
29
|
+
autoload :Scope, 'elasticshell/scopes'
|
30
|
+
autoload :Scopes, 'elasticshell/scopes'
|
31
|
+
autoload :Command, 'elasticshell/command'
|
32
|
+
autoload :Commands, 'elasticshell/command'
|
33
|
+
|
28
34
|
def self.version
|
29
35
|
@version ||= begin
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
36
|
+
File.read(File.expand_path('../../VERSION', __FILE__)).chomp
|
37
|
+
rescue => e
|
38
|
+
'unknown'
|
39
|
+
end
|
34
40
|
end
|
35
41
|
|
36
42
|
def self.start *args
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
if Settings.rest.length == 0
|
45
|
-
$stderr.puts "Starting with the --only option requires the first argument to name an API path (like `/_cluster/health')"
|
43
|
+
begin
|
44
|
+
case
|
45
|
+
when Settings[:version]
|
46
|
+
puts version
|
47
|
+
exit()
|
48
|
+
when Settings[:only] && Settings.rest.empty?
|
49
|
+
raise ArgumentError.new("Starting with the --only option requires a request argument (like `/_cluster/health')")
|
46
50
|
exit(1)
|
47
|
-
|
51
|
+
when (! Settings.rest.empty?)
|
52
|
+
es = Shell.new(Settings.merge(:log_requests => false))
|
53
|
+
es.connect
|
48
54
|
es.eval_line(Settings.rest.first)
|
49
55
|
exit()
|
56
|
+
else
|
57
|
+
Shell.new(Settings).run
|
50
58
|
end
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
55
|
-
es.run
|
59
|
+
rescue Elasticshell::Error => e
|
60
|
+
$stderr.puts e.message
|
61
|
+
exit(2)
|
56
62
|
end
|
57
63
|
end
|
58
|
-
|
59
64
|
end
|
data/lib/elasticshell/client.rb
CHANGED
@@ -1,23 +1,36 @@
|
|
1
1
|
require 'rubberband'
|
2
|
-
require 'elasticshell/error'
|
3
|
-
require 'elasticshell/log'
|
4
2
|
|
5
3
|
module Elasticshell
|
6
4
|
|
7
5
|
class Client
|
8
6
|
|
9
|
-
DEFAULT_SERVERS = ['http://localhost:9200']
|
10
|
-
|
11
7
|
def initialize options={}
|
12
|
-
@
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def connect options={}
|
12
|
+
servers = (options.merge(@options)[:servers] || Settings[:servers].to_s.split(","))
|
13
|
+
begin
|
14
|
+
@client = ElasticSearch::Client.new(servers)
|
15
|
+
rescue ElasticSearch::ConnectionFailed => e
|
16
|
+
raise ClientError.new("Could not connect to Elasticsearch server(s) at #{servers.join(',')}")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def connected?
|
21
|
+
@client
|
13
22
|
end
|
14
23
|
|
15
24
|
def request verb, params={}, options={}, body=''
|
25
|
+
raise ClientError.new("Not connected to any Elasticsearch servers.") unless connected?
|
16
26
|
safe = options.delete(:safely)
|
17
27
|
safe_return = options.delete(:return)
|
18
|
-
|
28
|
+
|
29
|
+
# Log by default
|
30
|
+
log_request(verb, params, options) unless options.delete(:log) == false
|
31
|
+
|
19
32
|
begin
|
20
|
-
|
33
|
+
perform_request(verb, params, options, body)
|
21
34
|
rescue ElasticSearch::RequestError, ArgumentError => e
|
22
35
|
if safe
|
23
36
|
safe_return
|
@@ -27,13 +40,21 @@ module Elasticshell
|
|
27
40
|
end
|
28
41
|
end
|
29
42
|
|
43
|
+
def perform_request verb, params, options, body
|
44
|
+
@client.execute(:standard_request, verb.downcase.to_sym, params, options, body)
|
45
|
+
end
|
46
|
+
|
30
47
|
def log_request verb, params, options={}
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
48
|
+
begin
|
49
|
+
# FIXME digging way too deep into rubberband here...is it really
|
50
|
+
# necessary?
|
51
|
+
uri = @client.instance_variable_get('@connection').send(:generate_uri, params)
|
52
|
+
query = @client.instance_variable_get('@connection').send(:generate_query_string, options)
|
53
|
+
path = [uri, query].reject { |s| s.nil? || s.strip.empty? }.join("?").gsub(Regexp.new("^/+"), "/")
|
54
|
+
Elasticshell.log("#{verb.to_s.upcase} #{path}".strip)
|
55
|
+
rescue
|
56
|
+
Elasticshell.log("#{verb.to_s.upcase} #{params.inspect} #{options.inspect}".strip)
|
57
|
+
end
|
37
58
|
end
|
38
59
|
|
39
60
|
def safely verb, params={}, options={}, body=''
|
data/lib/elasticshell/command.rb
CHANGED
@@ -1,12 +1,7 @@
|
|
1
|
-
require 'elasticshell/error'
|
2
|
-
require 'uri'
|
3
|
-
|
4
1
|
module Elasticshell
|
5
2
|
|
6
3
|
class Command
|
7
4
|
|
8
|
-
HTTP_VERB_RE = "(?:G(?:ET?)?|PO(?:ST?)?|PUT?|D(?:E(?:L(?:E(?:TE?)?)?)?)?)"
|
9
|
-
|
10
5
|
attr_accessor :shell, :input
|
11
6
|
|
12
7
|
def initialize shell, input
|
@@ -14,178 +9,27 @@ module Elasticshell
|
|
14
9
|
self.input = input
|
15
10
|
end
|
16
11
|
|
17
|
-
def
|
18
|
-
|
19
|
-
when setting_scope? then set_scope!
|
20
|
-
when setting_http_verb? then set_http_verb!
|
21
|
-
when making_explicit_req? then make_explicit_req!
|
22
|
-
when pretty? then pretty!
|
23
|
-
when help? then help!
|
24
|
-
when ls? then ls!
|
25
|
-
when blank? then nil
|
26
|
-
when scope_command? then run_scope_command!
|
27
|
-
else
|
28
|
-
raise ArgumentError.new("Unknown command '#{input}' for scope '#{shell.scope.path}'. Try typing 'help' for a list of available commands.")
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def setting_scope?
|
33
|
-
input =~ /^cd/
|
34
|
-
end
|
35
|
-
|
36
|
-
def set_scope!
|
37
|
-
if input =~ /^cd$/
|
38
|
-
shell.scope = Scopes.global(:client => shell.client)
|
39
|
-
return
|
40
|
-
end
|
41
|
-
|
42
|
-
return unless input =~ /^cd\s+(.+)$/
|
43
|
-
scope = $1
|
44
|
-
if scope =~ %r!^/!
|
45
|
-
shell.scope = Scopes.from_path(scope, :client => shell.client)
|
46
|
-
else
|
47
|
-
shell.scope = Scopes.from_path(File.expand_path(File.join(shell.scope.path, scope)), :client => shell.client)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def setting_http_verb?
|
52
|
-
input =~ Regexp.new("^" + HTTP_VERB_RE + "$", true)
|
53
|
-
end
|
54
|
-
|
55
|
-
def canonicalize_http_verb v
|
56
|
-
case v
|
57
|
-
when /^G/i then "GET"
|
58
|
-
when /^PO/i then "POST"
|
59
|
-
when /^PU/i then "PUT"
|
60
|
-
when /^D/i then "DELETE"
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def set_http_verb!
|
65
|
-
shell.verb = canonicalize_http_verb(input)
|
66
|
-
end
|
67
|
-
|
68
|
-
def scope_command?
|
69
|
-
shell.scope.command?(input)
|
70
|
-
end
|
71
|
-
|
72
|
-
def run_scope_command!
|
73
|
-
shell.scope.execute(input, shell)
|
74
|
-
end
|
75
|
-
|
76
|
-
def blank?
|
77
|
-
input.empty?
|
78
|
-
end
|
79
|
-
|
80
|
-
def help?
|
81
|
-
input =~ /^help/i
|
82
|
-
end
|
83
|
-
|
84
|
-
def help!
|
85
|
-
shell.scope.refresh
|
86
|
-
shell.print <<HELP
|
87
|
-
|
88
|
-
Globally available commands:
|
89
|
-
|
90
|
-
cd [PATH]
|
91
|
-
Change scope to the given path. Current path is reflected in the
|
92
|
-
prompt (it's '#{shell.scope.path}' right now).
|
93
|
-
|
94
|
-
Ex:
|
95
|
-
GET / > cd /my_index
|
96
|
-
GET /my_index > cd /other_index/some_type
|
97
|
-
GET /other_index/some_type
|
98
|
-
|
99
|
-
[get|post|put|delete]
|
100
|
-
Set the default HTTP verb (can use a non-ambiguous shortcut like 'g'
|
101
|
-
for 'GET' or 'pu' for 'PUT'). Current default HTTP verb is '#{shell.verb}'.
|
102
|
-
|
103
|
-
ls
|
104
|
-
Show what indices or mappings are within the current scope.
|
105
|
-
|
106
|
-
help
|
107
|
-
Show contextual help.
|
108
|
-
|
109
|
-
[VERB] PATH
|
110
|
-
Send an HTTP request with the given VERB to the given PATH
|
111
|
-
(including query string if given). If no verb is given, use the
|
112
|
-
default.
|
113
|
-
|
114
|
-
Ex: Simple search
|
115
|
-
GET / > /my_index/_search?q=query+string
|
116
|
-
{...}
|
117
|
-
|
118
|
-
Ex: Create an index
|
119
|
-
GET / > PUT /my_new_index
|
120
|
-
{...}
|
121
|
-
|
122
|
-
or
|
123
|
-
|
124
|
-
GET / > put
|
125
|
-
PUT / > /my_new_index
|
126
|
-
{...}
|
127
|
-
|
128
|
-
#{shell.scope.help}
|
129
|
-
HELP
|
12
|
+
def self.matches? input
|
13
|
+
raise NotImplementedError.new("Define the 'matches?' method on #{self.class}")
|
130
14
|
end
|
131
15
|
|
132
|
-
def
|
133
|
-
|
16
|
+
def be_connected!
|
17
|
+
raise ClientError.new("Not connected to any Elasticsearch servers.") unless shell.connected?
|
134
18
|
end
|
135
19
|
|
136
|
-
def
|
137
|
-
|
138
|
-
case
|
139
|
-
when input =~ /ll/
|
140
|
-
shell.print shell.scope.contents.join("\n")
|
141
|
-
else
|
142
|
-
shell.print shell.scope.contents.join(' ')
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
def pretty?
|
147
|
-
input =~ /pretty/i
|
148
|
-
end
|
149
|
-
|
150
|
-
def pretty!
|
151
|
-
if shell.pretty?
|
152
|
-
shell.not_pretty!
|
153
|
-
else
|
154
|
-
shell.pretty!
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
def making_explicit_req?
|
159
|
-
input =~ Regexp.new("^(" + HTTP_VERB_RE + "\s+)?/", true)
|
20
|
+
def evaluate!
|
21
|
+
raise NotImplementedError.new("Define the 'evaluate!' instance method in your subclass of #{self.class}")
|
160
22
|
end
|
23
|
+
end
|
161
24
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
path, query = path_and_query.split('?')
|
169
|
-
|
170
|
-
params = {}
|
171
|
-
keys = [:index, :type, :id, :op]
|
172
|
-
parts = path.gsub(%r!^/!,'').gsub(%r!/$!,'').split('/')
|
173
|
-
while parts.size > 0
|
174
|
-
part = parts.shift
|
175
|
-
key = (keys.shift or ArgumentError.new("The input '#{path}' has too many path components."))
|
176
|
-
params[key] = part
|
177
|
-
end
|
178
|
-
|
179
|
-
options = {}
|
180
|
-
URI.decode_www_form(query || '').each do |key, value|
|
181
|
-
options[key] = value
|
25
|
+
module Commands
|
26
|
+
PRIORITY = [].tap do |priority|
|
27
|
+
%w[cd pwd df connect help ls pretty set_verb blank request unknown].each do |command_name|
|
28
|
+
klass_name = command_name.split("_").map(&:capitalize).join("")
|
29
|
+
autoload klass_name.to_sym, "elasticshell/commands/#{command_name}"
|
30
|
+
priority << klass_name
|
182
31
|
end
|
183
|
-
|
184
|
-
shell.print(shell.client.request(verb.downcase.to_sym, params, options))
|
185
32
|
end
|
186
|
-
|
187
|
-
|
188
33
|
end
|
189
|
-
|
190
|
-
end
|
191
34
|
|
35
|
+
end
|