desi 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --no-private --protected lib/**/*.rb - README.md LICENSE
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ guard 'yard' do
4
+ watch(%r{lib/.+\.rb})
5
+ end
data/README.md CHANGED
@@ -2,8 +2,56 @@
2
2
 
3
3
  Desi (Developper ElasticSearch Installer) is very simple tool to quickly set up
4
4
  an [Elastic Search](http://www.elasticsearch.org/) local install for
5
- development purposes. It will download and install ElasticSearch (the latest
6
- version by default) and let you start/stop/restart it.
5
+ development purposes.
6
+
7
+ It can:
8
+
9
+ * download and install ElasticSearch (the latest release by default)
10
+ * start/stop/restart it.
11
+ * do basic indices management (list, delete, empty a given set of indices)
12
+
13
+ It can be used both as a command-line tool and as a library.
14
+
15
+
16
+ ## Usage
17
+
18
+ $ desi list # List locally installed ElasticSearch releases
19
+ $ desi releases # List all upstream Elastic Search releases (latest 5 by default)
20
+ $ desi install [VERSION] # Install a specific version (latest by default)
21
+ $ desi start # Start a local 1-node cluster (noop if active)
22
+ $ desi restart # (Re)start cluster (even if active)
23
+ $ desi stop # Stop cluster
24
+ $ desi status [--host HOST] # Show running cluster info
25
+
26
+ $ desi indices "^foo" # List all indices whose name match /^foo/
27
+ $ desi indices "^foo" --delete # Delete all matching indices
28
+ $ desi indices "bar$" --empty # Remove all records from the matching
29
+ # indices
30
+
31
+ ## Examples
32
+
33
+ ### Currently installed releases
34
+
35
+ The current version is the one symlinked to `$HOME/elasticsearch/current`
36
+
37
+ * command-line
38
+
39
+ ```shell
40
+ $ desi list
41
+ Local ES installs (current one is tagged with '*'):
42
+ * elasticsearch-0.19.9 (/home/me/elasticsearch/elasticsearch-0.19.9)
43
+ - elasticsearch-0.19.8 (/home/me/elasticsearch/elasticsearch-0.19.8)
44
+ ```
45
+
46
+
47
+ * library
48
+
49
+ ```ruby
50
+ Desi::LocalInstall.new.releases.map(&:name) #=> ["elasticsearch-0.19.8", "elasticsearch-0.19.9"]
51
+ Desi::LocalInstall.new.releases.detect(&:current?).version #=> "0.19.9"
52
+ ```
53
+
54
+
7
55
 
8
56
  ## Installation
9
57
 
@@ -19,21 +67,10 @@ Or install it yourself as:
19
67
 
20
68
  $ gem install desi
21
69
 
22
- ## Usage
23
-
24
- $ desi list # List locally installed ElasticSearch versions
25
- $ desi releases # List all upstream Elastic Search releases (latest 5 by default)
26
- $ desi install [VERSION] # Install a specific version (latest by default)
27
- $ desi start # Start a local 1-node cluster (noop if active)
28
- $ desi restart # (Re)start cluster (even if active)
29
- $ desi stop # Stop cluster
30
- $ desi status # Show running cluster info
31
-
32
70
  ## TODO
33
71
 
34
72
  * add tests, dammit!
35
73
 
36
- * index management (list, create, delete ES indices)
37
74
  * `desi upgrade` (Upgrade to latest version and migrate data)
38
75
  * `desi switch VERSION` (Switch currently active ES version to VERSION)
39
76
  * plugin management ? (list, install, remove ES plugins)
data/Rakefile CHANGED
@@ -1,2 +1,4 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
+
4
+ FileList['tasks/**/*.rake'].each { |task| import task }
data/desi.gemspec CHANGED
@@ -13,6 +13,11 @@ an Elastic Search local install for development purposes.}
13
13
 
14
14
  gem.add_dependency "boson"
15
15
  gem.add_dependency "cocaine"
16
+ gem.add_dependency "addressable"
17
+
18
+ gem.add_development_dependency "guard-yard"
19
+ gem.add_development_dependency "redcarpet"
20
+ gem.add_development_dependency "rb-inotify"
16
21
 
17
22
  gem.files = `git ls-files`.split($\)
18
23
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
data/lib/desi.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  require "desi/version"
2
2
 
3
3
  module Desi
4
- autoload :Downloader, 'desi/downloader'
5
- autoload :HttpClient, 'desi/http_client'
6
- autoload :LocalInstall, 'desi/local_install'
7
- autoload :Upstream, 'desi/upstream'
8
- autoload :Installer, 'desi/installer'
9
- autoload :ProcessManager, 'desi/process_manager'
4
+ require 'desi/downloader'
5
+ require 'desi/http_client'
6
+ require 'desi/local_install'
7
+ require 'desi/upstream'
8
+ require 'desi/installer'
9
+ require 'desi/process_manager'
10
+ require 'desi/index_manager'
10
11
  end
11
12
 
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require "net/https"
4
- require "uri"
4
+ require "addressable/uri"
5
5
  require "json"
6
6
 
7
7
  module Desi
@@ -10,8 +10,8 @@ module Desi
10
10
 
11
11
  attr_reader :uri
12
12
 
13
- def initialize(uri)
14
- @uri = URI(uri)
13
+ def initialize(host_string)
14
+ @uri = to_uri(host_string)
15
15
 
16
16
  case @uri.scheme
17
17
  when 'https'
@@ -39,6 +39,31 @@ module Desi
39
39
  raise response.error!
40
40
  end
41
41
  end
42
+
43
+ def delete(uri)
44
+ response = @http.request(Net::HTTP::Delete.new(uri))
45
+
46
+ case response
47
+ when Net::HTTPSuccess
48
+ response
49
+ else
50
+ raise response.error!
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def to_uri(host_string)
57
+ scheme, host, port = ['http', '127.0.0.1', 9200]
58
+
59
+ %r{(?<scheme>(https?|))(?:\:\/\/|)(?<host>[^:]*?):?(?<port>\d*)/?$}.match(host_string) do |m|
60
+ scheme = m[:scheme] unless m[:scheme].empty?
61
+ host = m[:host] unless m[:host].empty?
62
+ port = m[:port] unless m[:port].empty?
63
+ end
64
+
65
+ Addressable::URI.new(scheme: scheme, host: host, port: port)
66
+ end
42
67
  end
43
68
 
44
69
  end
@@ -0,0 +1,114 @@
1
+ # encoding: utf-8
2
+
3
+ require "desi/http_client"
4
+
5
+ module Desi
6
+
7
+ # Performs some simple index-related operations on a local or distance
8
+ # Elastic Search cluster
9
+ class IndexManager
10
+
11
+ # Initializes a Desi::IndexManager instance
12
+ #
13
+ # @param [#to_hash] opts Hash of extra 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
18
+ #
19
+ # @return [undefined]
20
+ #
21
+ # @api public
22
+ def initialize(opts = {})
23
+ @host = opts.fetch(:host, 'http://127.0.0.1:9200')
24
+ @verbose = opts[:verbose]
25
+ @client = Desi::HttpClient.new(@host)
26
+ end
27
+
28
+
29
+ # List index names for the specified cluster
30
+ #
31
+ # You can restrict the list using a regular expression pattern. (The default
32
+ # pattern being +/.*/+, all releases will be returned if you do not
33
+ # specify anything.)
34
+ #
35
+ # @param [#to_s] pattern Regexp pattern used to restrict the selection
36
+ # @return [Array<String>] List of index names of the ES cluster
37
+ #
38
+ # @note This method will also output its result on STDOUT if +@verbose+ is
39
+ # true
40
+ #
41
+ # @example List all indices whose name begins with "foo"
42
+ # Desi::IndexManager.new.list('^foo') #=> ["foo1", "foo2", "foo3"]
43
+ #
44
+ # @api public
45
+ def list(pattern = '.*')
46
+ pattern = Regexp.new(pattern || '.*')
47
+
48
+ puts "Indices from host #{@client.uri} matching the pattern #{pattern.inspect}\n\n" if @verbose
49
+
50
+ list = indices(pattern).sort
51
+ list.each {|i| puts i } if @verbose
52
+ list
53
+ end
54
+
55
+ # Delete all indices matching the specified pattern
56
+ #
57
+ # @param [#to_s] pattern Regexp pattern used to restrict the selection
58
+ # @return [undefined]
59
+ #
60
+ # @note No confirmation is needed, so beware!
61
+ #
62
+ # @note This method will also output its result on STDOUT if +@verbose+ is
63
+ # true
64
+ #
65
+ # @example Delete all indices whose name begins with "test"
66
+ # Desi::IndexManager.new.delete!('^test') #=> nil
67
+ #
68
+ # @api public
69
+ def delete!(pattern)
70
+ warn "You must provide a pattern" and exit if pattern.nil?
71
+
72
+ puts "The following indices from host #{@client.uri} are now deleted" if @verbose
73
+
74
+ indices(Regexp.new(pattern)).each do |index|
75
+ @client.delete(index)
76
+ puts " * #{index}" if @verbose
77
+ end
78
+ end
79
+
80
+ # Empty (remove all records) from indices matching the specified pattern
81
+ #
82
+ # @param [#to_s] pattern Regexp pattern used to restrict the selection
83
+ # @return [undefined]
84
+ #
85
+ # @note No confirmation is needed, so beware!
86
+ #
87
+ # @note This method will also output its result on STDOUT if +@verbose+ is
88
+ # true
89
+ #
90
+ # @example Empty all indices whose name begins with "log"
91
+ # Desi::IndexManager.new.empty!('^log') #=> nil
92
+ #
93
+ # @api public
94
+ def empty!(pattern)
95
+ warn "You must provide a pattern" and exit if pattern.nil?
96
+
97
+ puts "The following indices from host #{@client.uri} are now emptied" if @verbose
98
+
99
+ indices(Regexp.new(pattern)).each do |index|
100
+ @client.delete("#{index}/_query?q=*")
101
+ puts " * #{index}" if @verbose
102
+ end
103
+ end
104
+
105
+ private
106
+
107
+ def indices(pattern)
108
+ JSON.parse(@client.get('_status').body)["indices"].keys.select {|i|
109
+ i =~ pattern
110
+ }
111
+ end
112
+
113
+ end
114
+ end
@@ -1,9 +1,56 @@
1
1
  # encoding: utf-8
2
2
 
3
+ require "pathname"
4
+
3
5
  module Desi
4
6
  class LocalInstall
5
7
  DEFAULT_DIR = '~/elasticsearch'
6
8
 
9
+ class Release
10
+ def self.all_in(workdir)
11
+ Dir[workdir.join('*')].
12
+ select {|subdir| File.directory?(subdir) && File.basename(subdir) =~ /^elasticsearch\-\d+\.\d+\.\d+/ }.
13
+ map {|dirname| new(dirname, workdir) }
14
+ end
15
+
16
+ def initialize(dirname, workdir)
17
+ @dirname = Pathname.new(dirname)
18
+ @workdir = workdir
19
+ end
20
+
21
+ def name
22
+ @name ||= File.basename(@dirname)
23
+ end
24
+
25
+ def current?
26
+ current_symlink? && current_symlink.realpath == @dirname
27
+ end
28
+
29
+ def version
30
+ @version ||= /^elasticsearch\-(?<version>.*)$/.match(name.to_s)[:version]
31
+ end
32
+
33
+ def to_s
34
+ current_mark = current? ? '*' : '-'
35
+
36
+ " #{current_mark} #{name} (#{@dirname})"
37
+ end
38
+
39
+ def <=>(other)
40
+ name <=> other.name
41
+ end
42
+
43
+ private
44
+
45
+ def current_symlink
46
+ @current_symlink ||= Pathname(@workdir).join('current')
47
+ end
48
+
49
+ def current_symlink?
50
+ current_symlink.exist?
51
+ end
52
+ end
53
+
7
54
  def initialize(workdir = nil)
8
55
  @workdir = Pathname(File.expand_path(workdir || DEFAULT_DIR))
9
56
  end
@@ -20,8 +67,8 @@ module Desi
20
67
  FileUtils.mkdir_p @workdir
21
68
  end
22
69
 
23
- def versions
24
- Dir[@workdir.join('*')].select {|subdir| File.directory?(subdir) && File.basename(subdir) =~ /^elasticsearch\-\d+\.\d+\.\d+/ }
70
+ def releases
71
+ Release.all_in(@workdir)
25
72
  end
26
73
 
27
74
  def to_path
@@ -3,14 +3,17 @@
3
3
  require "json"
4
4
  require "cocaine"
5
5
  require "ostruct"
6
+ require "desi/http_client"
7
+ require "desi/local_install"
6
8
 
7
9
  module Desi
8
10
  class ProcessManager
9
11
 
10
12
  def initialize(opts = {})
13
+ @host = opts.fetch(:host, 'http://127.0.0.1:9200')
11
14
  @verbose = opts[:verbose]
12
15
  @local_install = LocalInstall.new
13
- @client = Desi::HttpClient.new('http://localhost:9200/')
16
+ @client = Desi::HttpClient.new(@host)
14
17
  end
15
18
 
16
19
  def start
data/lib/desi/runner.rb CHANGED
@@ -13,9 +13,9 @@ module Desi
13
13
  desc "List locally installed Elastic Search releases"
14
14
  verbosity_option
15
15
  def list(options = {})
16
- puts "Local ES installs:" unless quiet?(options)
17
- Desi::LocalInstall.new.versions.each do |v|
18
- puts "* #{v}"
16
+ puts "Local ES installs (current one is tagged with '*'):" unless quiet?(options)
17
+ Desi::LocalInstall.new.releases.sort.reverse.each do |v|
18
+ puts v
19
19
  end
20
20
  end
21
21
 
@@ -31,7 +31,7 @@ module Desi
31
31
  releases
32
32
  else
33
33
  puts "Here are #{limit == 0 ? 'all the' : "the #{limit} latest"} releases"
34
- releases.each {|rel| puts " * #{rel.name} (#{rel.release_date})" }
34
+ releases.each {|rel| puts " - #{rel.name} (#{rel.release_date})" }
35
35
  end
36
36
  end
37
37
 
@@ -71,8 +71,26 @@ module Desi
71
71
 
72
72
  desc "Show current status"
73
73
  verbosity_option
74
+ option "--host", type: :string, desc: "Elastic Search cluster URL", default: '127.0.0.1:9200'
74
75
  def status(options = {})
75
- Desi::ProcessManager.new(verbose: !quiet?(options)).status
76
+ Desi::ProcessManager.new(verbose: !quiet?(options), host: options[:host]).status
77
+ end
78
+
79
+ desc "List indices"
80
+ verbosity_option
81
+ option "--host", type: :string, desc: "Elastic Search cluster URL", default: '127.0.0.1:9200'
82
+ option "--delete", type: :boolean, desc: "Delete the specified indices (You've been warned!)", default: false
83
+ option "--empty", type: :boolean, desc: "Delete all documents from the specified indices", default: false
84
+ def indices(pattern = nil, options = {})
85
+ index_manager = Desi::IndexManager.new(verbose: !quiet?(options), host: options[:host])
86
+
87
+ if options[:delete]
88
+ index_manager.delete!(pattern)
89
+ elsif options[:empty]
90
+ index_manager.empty!(pattern)
91
+ else
92
+ index_manager.list(pattern)
93
+ end
76
94
  end
77
95
 
78
96
  # desc "Upgrade to latest ElasticSearch version"
data/lib/desi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Desi
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
data/tasks/yard.rake ADDED
@@ -0,0 +1,9 @@
1
+ begin
2
+ require 'yard'
3
+
4
+ YARD::Rake::YardocTask.new
5
+ rescue LoadError
6
+ task :yard do
7
+ abort 'YARD is not available. In order to run yard, you must: gem install yard'
8
+ end
9
+ 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.0.2
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-17 00:00:00.000000000 Z
12
+ date: 2012-09-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: boson
@@ -43,6 +43,70 @@ dependencies:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: addressable
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: guard-yard
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: redcarpet
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: rb-inotify
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'
46
110
  description: ! 'Desi (Developper ElasticSearch Installer) is very simple tool to quickly
47
111
  set up
48
112
 
@@ -55,7 +119,9 @@ extensions: []
55
119
  extra_rdoc_files: []
56
120
  files:
57
121
  - .gitignore
122
+ - .yardopts
58
123
  - Gemfile
124
+ - Guardfile
59
125
  - LICENSE
60
126
  - README.md
61
127
  - Rakefile
@@ -65,12 +131,14 @@ files:
65
131
  - lib/desi.rb
66
132
  - lib/desi/downloader.rb
67
133
  - lib/desi/http_client.rb
134
+ - lib/desi/index_manager.rb
68
135
  - lib/desi/installer.rb
69
136
  - lib/desi/local_install.rb
70
137
  - lib/desi/process_manager.rb
71
138
  - lib/desi/runner.rb
72
139
  - lib/desi/upstream.rb
73
140
  - lib/desi/version.rb
141
+ - tasks/yard.rake
74
142
  homepage: https://github.com/AF83/desi/
75
143
  licenses: []
76
144
  post_install_message: