desi 0.1.0 → 0.2.0
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/.rspec +2 -0
- data/Guardfile +6 -0
- data/README.md +55 -7
- data/desi.gemspec +3 -0
- data/lib/desi/downloader.rb +1 -1
- data/lib/desi/http_client.rb +0 -2
- data/lib/desi/index_manager.rb +19 -14
- data/lib/desi/process_manager.rb +2 -2
- data/lib/desi/upstream.rb +3 -2
- data/lib/desi/version.rb +1 -1
- data/spec/desi/index_manager_spec.rb +134 -0
- data/spec/spec_helper.rb +11 -0
- metadata +61 -2
data/.rspec
ADDED
data/Guardfile
CHANGED
data/README.md
CHANGED
@@ -13,7 +13,7 @@ It can:
|
|
13
13
|
It can be used both as a command-line tool and as a library.
|
14
14
|
|
15
15
|
|
16
|
-
## Usage
|
16
|
+
## Usage (command-line)
|
17
17
|
|
18
18
|
$ desi list # List locally installed ElasticSearch releases
|
19
19
|
$ desi releases # List all upstream Elastic Search releases (latest 5 by default)
|
@@ -25,14 +25,14 @@ It can be used both as a command-line tool and as a library.
|
|
25
25
|
|
26
26
|
$ desi indices "^foo" # List all indices whose name match /^foo/
|
27
27
|
$ desi indices "^foo" --delete # Delete all matching indices
|
28
|
-
$ desi indices "bar$" --empty # Remove all records from the matching
|
29
|
-
# indices
|
28
|
+
$ desi indices "bar$" --empty # Remove all records from the matching indices
|
30
29
|
|
31
|
-
## Examples
|
30
|
+
## Examples (command-line and Ruby)
|
32
31
|
|
33
|
-
###
|
32
|
+
### Get the list of locally installed releases
|
34
33
|
|
35
|
-
The current version is the one symlinked to `$HOME/elasticsearch/current
|
34
|
+
The current version is the one symlinked to `$HOME/elasticsearch/current`, that
|
35
|
+
will be spun up by (`desi start`)
|
36
36
|
|
37
37
|
* command-line
|
38
38
|
|
@@ -52,6 +52,54 @@ The current version is the one symlinked to `$HOME/elasticsearch/current`
|
|
52
52
|
```
|
53
53
|
|
54
54
|
|
55
|
+
### List and delete some indices
|
56
|
+
|
57
|
+
* command-line
|
58
|
+
|
59
|
+
```shell
|
60
|
+
$ # List all local indices
|
61
|
+
$ desi indices
|
62
|
+
Indices from host http://127.0.0.1:9200 matching the pattern /.*/
|
63
|
+
|
64
|
+
foo
|
65
|
+
bar
|
66
|
+
baz
|
67
|
+
|
68
|
+
$ # List all indices on remote cluster 129.168.1.42, reachable on port 9800
|
69
|
+
$ desi indices --host 129.168.1.42:9800 foo
|
70
|
+
Indices from host http://192.168.1.42:9800 matching the pattern /foo/
|
71
|
+
|
72
|
+
remotefoo1
|
73
|
+
remotefoo2
|
74
|
+
|
75
|
+
$ # Remove all indices whose name starts with "ba"
|
76
|
+
$ desi indices --delete "^ba"
|
77
|
+
The following indices from host http://127.0.0.1:9200 are now deleted
|
78
|
+
* bar
|
79
|
+
* baz
|
80
|
+
```
|
81
|
+
|
82
|
+
|
83
|
+
* library
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
# All local indices
|
87
|
+
Desi::IndexManager.new.list #=> ["foo", "bar", "baz"]
|
88
|
+
|
89
|
+
# All local indices whose name starts with `b`
|
90
|
+
Desi::IndexManager.new.list("^b") #=> ["bar", "baz"]
|
91
|
+
|
92
|
+
# All indices from distant cluster
|
93
|
+
Desi::IndexManager.new(host: "192.168.1.42:9800").list #=> ["remotefoo1", "remotefoo2"]
|
94
|
+
|
95
|
+
# Delete all local indices whose name starts with `ba`
|
96
|
+
Desi::IndexManager.new.delete!("^ba") #=> nil
|
97
|
+
|
98
|
+
# The indices actually disappeared
|
99
|
+
Desi::IndexManager.new.list #=> ["foo"]
|
100
|
+
```
|
101
|
+
|
102
|
+
|
55
103
|
|
56
104
|
## Installation
|
57
105
|
|
@@ -69,7 +117,7 @@ Or install it yourself as:
|
|
69
117
|
|
70
118
|
## TODO
|
71
119
|
|
72
|
-
* add tests
|
120
|
+
* add more tests
|
73
121
|
|
74
122
|
* `desi upgrade` (Upgrade to latest version and migrate data)
|
75
123
|
* `desi switch VERSION` (Switch currently active ES version to VERSION)
|
data/desi.gemspec
CHANGED
@@ -15,6 +15,9 @@ an Elastic Search local install for development purposes.}
|
|
15
15
|
gem.add_dependency "cocaine"
|
16
16
|
gem.add_dependency "addressable"
|
17
17
|
|
18
|
+
gem.add_development_dependency "rake"
|
19
|
+
gem.add_development_dependency "rspec"
|
20
|
+
gem.add_development_dependency "guard-rspec"
|
18
21
|
gem.add_development_dependency "guard-yard"
|
19
22
|
gem.add_development_dependency "redcarpet"
|
20
23
|
gem.add_development_dependency "rb-inotify"
|
data/lib/desi/downloader.rb
CHANGED
@@ -11,7 +11,7 @@ module Desi
|
|
11
11
|
def initialize(opts = {})
|
12
12
|
@destination_dir = Pathname(opts.fetch(:destination_dir, Desi::LocalInstall.new))
|
13
13
|
@host = URI(opts.fetch(:host, 'http://cloud.github.com/'))
|
14
|
-
@client = Desi::HttpClient.new(@host)
|
14
|
+
@client = opts.fetch(:http_client_factory, Desi::HttpClient).new(@host)
|
15
15
|
@verbose = opts[:verbose]
|
16
16
|
end
|
17
17
|
|
data/lib/desi/http_client.rb
CHANGED
data/lib/desi/index_manager.rb
CHANGED
@@ -10,19 +10,24 @@ module Desi
|
|
10
10
|
|
11
11
|
# Initializes a Desi::IndexManager instance
|
12
12
|
#
|
13
|
-
# @param [#to_hash] opts
|
14
|
-
# @option opts [#to_s] :host Host to manage indices for
|
15
|
-
# (default: 'http://127.0.0.1:9200')
|
16
|
-
# @option opts [Boolean] :verbose Whether to output the actions' result
|
17
|
-
# on STDOUT
|
13
|
+
# @param [#to_hash] opts Hash of extra opts
|
18
14
|
#
|
15
|
+
# @option opts [#to_s] :host ('http://127.0.0.1:9200') Host to manage indices for
|
16
|
+
# @option opts [Boolean] :verbose (nil) Whether to output the actions' result
|
17
|
+
# on STDOUT
|
18
|
+
# @option opts [#new] :http_client_factory (Desi::HttpClient) HTTP transport class
|
19
|
+
# to use
|
20
|
+
#
|
21
|
+
# @note The +:http_client_factory+ should return an instance that responds
|
22
|
+
# to #get and #delete
|
19
23
|
# @return [undefined]
|
20
24
|
#
|
21
25
|
# @api public
|
22
26
|
def initialize(opts = {})
|
23
27
|
@host = opts.fetch(:host, 'http://127.0.0.1:9200')
|
24
28
|
@verbose = opts[:verbose]
|
25
|
-
@
|
29
|
+
@outputter = opts.fetch(:outputter, Kernel)
|
30
|
+
@client = opts.fetch(:http_client_factory, Desi::HttpClient).new(@host)
|
26
31
|
end
|
27
32
|
|
28
33
|
|
@@ -32,8 +37,8 @@ module Desi
|
|
32
37
|
# pattern being +/.*/+, all releases will be returned if you do not
|
33
38
|
# specify anything.)
|
34
39
|
#
|
35
|
-
# @param [#to_s] pattern
|
36
|
-
# @return [Array<String>]
|
40
|
+
# @param [#to_s] pattern ('.*') Regexp pattern used to restrict the selection
|
41
|
+
# @return [Array<String>] List of index names of the ES cluster
|
37
42
|
#
|
38
43
|
# @note This method will also output its result on STDOUT if +@verbose+ is
|
39
44
|
# true
|
@@ -45,10 +50,10 @@ module Desi
|
|
45
50
|
def list(pattern = '.*')
|
46
51
|
pattern = Regexp.new(pattern || '.*')
|
47
52
|
|
48
|
-
puts "Indices from host #{@
|
53
|
+
@outputter.puts "Indices from host #{@host} matching the pattern #{pattern.inspect}\n\n" if @verbose
|
49
54
|
|
50
55
|
list = indices(pattern).sort
|
51
|
-
list.each {|i| puts i } if @verbose
|
56
|
+
list.each {|i| @outputter.puts i } if @verbose
|
52
57
|
list
|
53
58
|
end
|
54
59
|
|
@@ -69,11 +74,11 @@ module Desi
|
|
69
74
|
def delete!(pattern)
|
70
75
|
warn "You must provide a pattern" and exit if pattern.nil?
|
71
76
|
|
72
|
-
puts "The following indices from host #{@
|
77
|
+
@outputter.puts "The following indices from host #{@host} are now deleted" if @verbose
|
73
78
|
|
74
79
|
indices(Regexp.new(pattern)).each do |index|
|
75
80
|
@client.delete(index)
|
76
|
-
puts " * #{index}" if @verbose
|
81
|
+
@outputter.puts " * #{index}" if @verbose
|
77
82
|
end
|
78
83
|
end
|
79
84
|
|
@@ -94,11 +99,11 @@ module Desi
|
|
94
99
|
def empty!(pattern)
|
95
100
|
warn "You must provide a pattern" and exit if pattern.nil?
|
96
101
|
|
97
|
-
puts "The following indices from host #{@
|
102
|
+
@outputter.puts "The following indices from host #{@host} are now emptied" if @verbose
|
98
103
|
|
99
104
|
indices(Regexp.new(pattern)).each do |index|
|
100
105
|
@client.delete("#{index}/_query?q=*")
|
101
|
-
puts " * #{index}" if @verbose
|
106
|
+
@outputter.puts " * #{index}" if @verbose
|
102
107
|
end
|
103
108
|
end
|
104
109
|
|
data/lib/desi/process_manager.rb
CHANGED
@@ -13,7 +13,7 @@ module Desi
|
|
13
13
|
@host = opts.fetch(:host, 'http://127.0.0.1:9200')
|
14
14
|
@verbose = opts[:verbose]
|
15
15
|
@local_install = LocalInstall.new
|
16
|
-
@client = Desi::HttpClient.new(@host)
|
16
|
+
@client = opts.fetch(:http_client_factory, Desi::HttpClient).new(@host)
|
17
17
|
end
|
18
18
|
|
19
19
|
def start
|
@@ -50,7 +50,7 @@ module Desi
|
|
50
50
|
if version = running_version
|
51
51
|
msg = "OK. Elastic Search cluster '#{cluster_health.cluster_name}' (v#{version}) is running on #{cluster_health.number_of_nodes} node(s) with status #{cluster_health.status}"
|
52
52
|
else
|
53
|
-
msg = "KO. No Elastic Search instance was found running on #{@
|
53
|
+
msg = "KO. No Elastic Search instance was found running on #{@host}"
|
54
54
|
end
|
55
55
|
puts msg if @verbose
|
56
56
|
msg
|
data/lib/desi/upstream.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require "desi/http_client"
|
4
|
+
require "json"
|
4
5
|
|
5
6
|
module Desi
|
6
7
|
class Upstream
|
@@ -11,8 +12,8 @@ module Desi
|
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
14
|
-
def initialize
|
15
|
-
@client = Desi::HttpClient.new('https://api.github.com/')
|
15
|
+
def initialize(opts = {})
|
16
|
+
@client = opts.fetch(:http_client_factory, Desi::HttpClient).new('https://api.github.com/')
|
16
17
|
end
|
17
18
|
|
18
19
|
def releases
|
data/lib/desi/version.rb
CHANGED
@@ -0,0 +1,134 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
require "desi/index_manager"
|
5
|
+
require "json"
|
6
|
+
|
7
|
+
describe Desi::IndexManager do
|
8
|
+
|
9
|
+
subject { described_class.new(http_client_factory: http_client_factory) }
|
10
|
+
|
11
|
+
let(:http_client_factory) { double(new: http_client) }
|
12
|
+
let(:http_client) { double('http_client') }
|
13
|
+
|
14
|
+
def stub_request(method, path, payload)
|
15
|
+
http_client.stub(method).with(path).and_return(
|
16
|
+
mock("response", body: JSON.unparse(payload))
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def stub_indices(*names)
|
21
|
+
stub_request(:get, '_status', {"indices" => Hash[Array(names).zip]})
|
22
|
+
end
|
23
|
+
|
24
|
+
before do
|
25
|
+
stub_indices('foo', 'bar')
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#list" do
|
29
|
+
context "with no specified pattern" do
|
30
|
+
it "returns the names of all indices" do
|
31
|
+
subject.list.should == %w[bar foo]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "with a pattern" do
|
36
|
+
it "returns the matching indices" do
|
37
|
+
subject.list('oo').should == %w[foo]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when verbose is on" do
|
42
|
+
let(:outputter) { double("outputter") }
|
43
|
+
|
44
|
+
subject do
|
45
|
+
described_class.new(
|
46
|
+
http_client_factory: http_client_factory,
|
47
|
+
outputter: outputter,
|
48
|
+
verbose: true)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "also outputs on STDOUT" do
|
52
|
+
outputter.should_receive(:puts).at_least(:once)
|
53
|
+
subject.list('oo')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#delete!" do
|
59
|
+
context "when the mandatory pattern is not specified" do
|
60
|
+
it "raises an ArgumentError" do
|
61
|
+
expect { subject.delete! }.to raise_error(ArgumentError)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it "deletes all matching indices" do
|
66
|
+
http_client.should_receive(:delete).with("foo")
|
67
|
+
http_client.should_not_receive(:delete).with("bar")
|
68
|
+
|
69
|
+
subject.delete!('f.*')
|
70
|
+
end
|
71
|
+
|
72
|
+
context "when verbose is on" do
|
73
|
+
let(:outputter) { double("outputter") }
|
74
|
+
|
75
|
+
subject do
|
76
|
+
described_class.new(
|
77
|
+
http_client_factory: http_client_factory,
|
78
|
+
outputter: outputter,
|
79
|
+
verbose: true)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "also outputs on STDOUT" do
|
83
|
+
http_client.stub(:delete)
|
84
|
+
|
85
|
+
outputter.should_receive(:puts).at_least(:once)
|
86
|
+
subject.delete!('f.*')
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#empty!" do
|
92
|
+
context "when the mandatory pattern is not specified" do
|
93
|
+
it "raises an ArgumentError" do
|
94
|
+
expect { subject.empty! }.to raise_error(ArgumentError)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it "deletes all matching indices" do
|
99
|
+
http_client.should_receive(:delete).with("foo/_query?q=*")
|
100
|
+
http_client.should_not_receive(:delete).with("bar")
|
101
|
+
|
102
|
+
subject.empty!('f.*')
|
103
|
+
end
|
104
|
+
|
105
|
+
context "when verbose is on" do
|
106
|
+
let(:outputter) { double("outputter") }
|
107
|
+
|
108
|
+
subject do
|
109
|
+
described_class.new(
|
110
|
+
http_client_factory: http_client_factory,
|
111
|
+
outputter: outputter,
|
112
|
+
verbose: true)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "also outputs on STDOUT" do
|
116
|
+
http_client.stub(:delete)
|
117
|
+
|
118
|
+
outputter.should_receive(:puts).at_least(:once)
|
119
|
+
subject.empty!('f.*')
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context "when given another host" do
|
125
|
+
let(:factory_for_remote_host) { double("http_client_factory") }
|
126
|
+
|
127
|
+
it "sends the other host's url to initialize the client" do
|
128
|
+
factory_for_remote_host.should_receive(:new).with("http://foobar.com")
|
129
|
+
|
130
|
+
described_class.new(host: "http://foobar.com", http_client_factory: factory_for_remote_host)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
RSpec.configure do |config|
|
2
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
3
|
+
config.run_all_when_everything_filtered = true
|
4
|
+
config.filter_run :focus
|
5
|
+
|
6
|
+
# Run specs in random order to surface order dependencies. If you find an
|
7
|
+
# order dependency and want to debug it, you can fix the order by providing
|
8
|
+
# the seed, which is printed after each run.
|
9
|
+
# --seed 1234
|
10
|
+
config.order = 'random'
|
11
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: desi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -59,6 +59,54 @@ dependencies:
|
|
59
59
|
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rspec
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: guard-rspec
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
62
110
|
- !ruby/object:Gem::Dependency
|
63
111
|
name: guard-yard
|
64
112
|
requirement: !ruby/object:Gem::Requirement
|
@@ -119,6 +167,7 @@ extensions: []
|
|
119
167
|
extra_rdoc_files: []
|
120
168
|
files:
|
121
169
|
- .gitignore
|
170
|
+
- .rspec
|
122
171
|
- .yardopts
|
123
172
|
- Gemfile
|
124
173
|
- Guardfile
|
@@ -138,6 +187,8 @@ files:
|
|
138
187
|
- lib/desi/runner.rb
|
139
188
|
- lib/desi/upstream.rb
|
140
189
|
- lib/desi/version.rb
|
190
|
+
- spec/desi/index_manager_spec.rb
|
191
|
+
- spec/spec_helper.rb
|
141
192
|
- tasks/yard.rake
|
142
193
|
homepage: https://github.com/AF83/desi/
|
143
194
|
licenses: []
|
@@ -151,17 +202,25 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
151
202
|
- - ! '>='
|
152
203
|
- !ruby/object:Gem::Version
|
153
204
|
version: '0'
|
205
|
+
segments:
|
206
|
+
- 0
|
207
|
+
hash: 1725098947325688636
|
154
208
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
155
209
|
none: false
|
156
210
|
requirements:
|
157
211
|
- - ! '>='
|
158
212
|
- !ruby/object:Gem::Version
|
159
213
|
version: '0'
|
214
|
+
segments:
|
215
|
+
- 0
|
216
|
+
hash: 1725098947325688636
|
160
217
|
requirements: []
|
161
218
|
rubyforge_project:
|
162
219
|
rubygems_version: 1.8.24
|
163
220
|
signing_key:
|
164
221
|
specification_version: 3
|
165
222
|
summary: A developer tool to quickly set up an Elastic Search local install.
|
166
|
-
test_files:
|
223
|
+
test_files:
|
224
|
+
- spec/desi/index_manager_spec.rb
|
225
|
+
- spec/spec_helper.rb
|
167
226
|
has_rdoc:
|