elastomer-client 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.ruby-version +1 -0
  4. data/CHANGELOG.md +4 -0
  5. data/Gemfile +5 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +108 -0
  8. data/Rakefile +9 -0
  9. data/docs/notifications.md +71 -0
  10. data/elastomer-client.gemspec +30 -0
  11. data/lib/elastomer/client.rb +307 -0
  12. data/lib/elastomer/client/bulk.rb +257 -0
  13. data/lib/elastomer/client/cluster.rb +208 -0
  14. data/lib/elastomer/client/docs.rb +432 -0
  15. data/lib/elastomer/client/errors.rb +51 -0
  16. data/lib/elastomer/client/index.rb +407 -0
  17. data/lib/elastomer/client/multi_search.rb +115 -0
  18. data/lib/elastomer/client/nodes.rb +87 -0
  19. data/lib/elastomer/client/scan.rb +161 -0
  20. data/lib/elastomer/client/template.rb +85 -0
  21. data/lib/elastomer/client/warmer.rb +96 -0
  22. data/lib/elastomer/core_ext/time.rb +7 -0
  23. data/lib/elastomer/middleware/encode_json.rb +51 -0
  24. data/lib/elastomer/middleware/opaque_id.rb +69 -0
  25. data/lib/elastomer/middleware/parse_json.rb +39 -0
  26. data/lib/elastomer/notifications.rb +83 -0
  27. data/lib/elastomer/version.rb +7 -0
  28. data/script/bootstrap +16 -0
  29. data/script/cibuild +28 -0
  30. data/script/console +9 -0
  31. data/script/testsuite +10 -0
  32. data/test/assertions.rb +74 -0
  33. data/test/client/bulk_test.rb +226 -0
  34. data/test/client/cluster_test.rb +113 -0
  35. data/test/client/docs_test.rb +394 -0
  36. data/test/client/index_test.rb +244 -0
  37. data/test/client/multi_search_test.rb +129 -0
  38. data/test/client/nodes_test.rb +35 -0
  39. data/test/client/scan_test.rb +84 -0
  40. data/test/client/stubbed_client_tests.rb +40 -0
  41. data/test/client/template_test.rb +33 -0
  42. data/test/client/warmer_test.rb +56 -0
  43. data/test/client_test.rb +86 -0
  44. data/test/core_ext/time_test.rb +46 -0
  45. data/test/middleware/encode_json_test.rb +53 -0
  46. data/test/middleware/opaque_id_test.rb +39 -0
  47. data/test/middleware/parse_json_test.rb +54 -0
  48. data/test/test_helper.rb +94 -0
  49. metadata +210 -0
@@ -0,0 +1,87 @@
1
+
2
+ module Elastomer
3
+ class Client
4
+
5
+ # Provides access to node-level API commands.
6
+ #
7
+ # node_id - The node ID as a String or an Array of node IDs
8
+ #
9
+ # Returns a Nodes instance.
10
+ def nodes( node_id = '_all' )
11
+ Nodes.new self, node_id
12
+ end
13
+
14
+
15
+ class Nodes
16
+ # Create a new nodes client for making API requests that pertain to
17
+ # the health and management individual nodes.
18
+ #
19
+ # client - Elastomer::Client used for HTTP requests to the server
20
+ # node_id - The node ID as a String or an Array of node IDs
21
+ #
22
+ def initialize( client, node_id )
23
+ @client = client
24
+ @node_id = node_id
25
+ end
26
+
27
+ attr_reader :client, :node_id
28
+
29
+ # Retrieve one or more (or all) of the cluster nodes information.
30
+ # See http://www.elasticsearch.org/guide/reference/api/admin-cluster-nodes-info/
31
+ #
32
+ # params - Parameters Hash
33
+ #
34
+ # Returns the response as a Hash
35
+ def info( params = {} )
36
+ response = client.get '/_nodes{/node_id}', update_params(params, :action => 'nodes.info')
37
+ response.body
38
+ end
39
+
40
+ # Retrieve one or more (or all) of the cluster nodes statistics.
41
+ # See http://www.elasticsearch.org/guide/reference/api/admin-cluster-nodes-stats/
42
+ #
43
+ # params - Parameters Hash
44
+ #
45
+ # Returns the response as a Hash
46
+ def stats( params = {} )
47
+ response = client.get '/_nodes{/node_id}/stats', update_params(params, :action => 'nodes.stats')
48
+ response.body
49
+ end
50
+
51
+ # Get the current hot threads on each node in the cluster.
52
+ # See http://www.elasticsearch.org/guide/reference/api/admin-cluster-nodes-hot-threads/
53
+ #
54
+ # params - Parameters Hash
55
+ #
56
+ # Returns the response as a Hash
57
+ def hot_threads( params = {} )
58
+ response = client.get '/_nodes{/node_id}/hot_threads', update_params(params, :action => 'nodes.hot_threads')
59
+ response.body
60
+ end
61
+
62
+ # Shutdown one or more nodes in the cluster.
63
+ # See http://www.elasticsearch.org/guide/reference/api/admin-cluster-nodes-shutdown/
64
+ #
65
+ # params - Parameters Hash
66
+ #
67
+ # Returns the response as a Hash
68
+ def shutdown( params = {} )
69
+ response = client.post '/_cluster/nodes{/node_id}/_shutdown', update_params(params, :action => 'nodes.shutdown')
70
+ response.body
71
+ end
72
+
73
+ # Internal: Add default parameters to the `params` Hash and then apply
74
+ # `overrides` to the params if any are given.
75
+ #
76
+ # params - Parameters Hash
77
+ # overrides - Optional parameter overrides as a Hash
78
+ #
79
+ # Returns a new params Hash.
80
+ def update_params( params, overrides = nil )
81
+ h = { :node_id => node_id }.update params
82
+ h.update overrides unless overrides.nil?
83
+ h
84
+ end
85
+ end # Nodes
86
+ end # Client
87
+ end # Elastomer
@@ -0,0 +1,161 @@
1
+ module Elastomer
2
+ class Client
3
+
4
+ # Create a new Scan instance for scrolling all results from a `query`.
5
+ #
6
+ # query - The query to scan as a Hash or a JSON encoded String
7
+ # opts - Options Hash
8
+ # :index - the name of the index to search
9
+ # :type - the document type to search
10
+ # :scroll - the keep alive time of the scrolling request (5 minutes by default)
11
+ # :size - the number of documents per shard to fetch per scroll
12
+ #
13
+ # Examples
14
+ #
15
+ # scan = client.scan('{"query":{"match_all":{}}}', :index => 'test')
16
+ # scan.each_document do |document|
17
+ # document['_id']
18
+ # document['_source']
19
+ # end
20
+ #
21
+ # Returns a new Scan instance
22
+ def scan( query, opts = {} )
23
+ Scan.new self, query, opts
24
+ end
25
+
26
+ # Continue scrolling a scan query.
27
+ # See http://www.elasticsearch.org/guide/reference/api/search/scroll/
28
+ #
29
+ # scroll_id - The current scroll ID as a String
30
+ # scroll - The keep alive time of the scrolling request (5 minutes by default)
31
+ #
32
+ # Examples
33
+ #
34
+ # scroll_id = client.scan('{"query":{"match_all":{}}}', :index => 'test').scroll_id
35
+ #
36
+ # h = client.scroll scroll_id # scroll to get the next set of results
37
+ # scroll_id = h['_scroll_id'] # and store the scroll_id to use later
38
+ #
39
+ # h = client.scroll scroll_id # scroll again to get the next set of results
40
+ # scroll_id = h['_scroll_id'] # and store the scroll_id to use later
41
+ #
42
+ # # repeat until the results are empty
43
+ #
44
+ # Returns the response body as a Hash.
45
+ def scroll( scroll_id, scroll = '5m' )
46
+ response = get '/_search/scroll', :body => scroll_id, :scroll => scroll, :action => 'search.scroll'
47
+ response.body
48
+ end
49
+
50
+
51
+ class Scan
52
+ # Create a new scan client that can be used to iterate over all the
53
+ # documents returned by the `query`.
54
+ #
55
+ # See http://www.elasticsearch.org/guide/reference/api/search/scroll/
56
+ # and the "Scan" section of http://www.elasticsearch.org/guide/reference/api/search/search-type/
57
+ #
58
+ # client - Elastomer::Client used for HTTP requests to the server
59
+ # query - The query to scan as a Hash or a JSON encoded String
60
+ # opts - Options Hash
61
+ # :index - the name of the index to search
62
+ # :type - the document type to search
63
+ # :scroll - the keep alive time of the scrolling request (5 minutes by default)
64
+ # :size - the number of documents per shard to fetch per scroll
65
+ #
66
+ # Examples
67
+ #
68
+ # scan = Scan.new(client, {:query => {:match_all => {}}}, :index => 'test-1')
69
+ # scan.each_document { |doc|
70
+ # doc['_id']
71
+ # doc['_source']
72
+ # }
73
+ #
74
+ def initialize( client, query, opts = {} )
75
+ @client = client
76
+ @query = query
77
+
78
+ @index = opts.fetch(:index, nil)
79
+ @type = opts.fetch(:type, nil)
80
+ @scroll = opts.fetch(:scroll, '5m')
81
+ @size = opts.fetch(:size, 50)
82
+
83
+ @offset = 0
84
+ end
85
+
86
+ attr_reader :client, :query, :index, :type, :scroll, :size
87
+
88
+ # Iterate over all the search results from the scan query.
89
+ #
90
+ # block - The block will be called for each set of matching documents
91
+ # returned from executing the scan query.
92
+ #
93
+ # Yields a hits Hash containing the 'total' number of hits, current
94
+ # 'offset' into that total, and the Array of 'hits' document Hashes.
95
+ #
96
+ # Examples
97
+ #
98
+ # scan.each do |hits|
99
+ # hits['total']
100
+ # hits['offset']
101
+ # hits['hits'].each { |document| ... }
102
+ # end
103
+ #
104
+ # Returns this Scan instance.
105
+ def each
106
+ loop do
107
+ body = client.scroll scroll_id, scroll
108
+ @scroll_id = body['_scroll_id']
109
+
110
+ hits = body['hits']
111
+ break if hits['hits'].empty?
112
+
113
+ hits['offset'] = @offset
114
+ @offset += hits['hits'].length
115
+
116
+ yield hits
117
+ end
118
+
119
+ self
120
+ end
121
+
122
+ # Iterate over each document from the scan query. This method is just a
123
+ # convenience wrapper around the `each` method; it iterates the Array of
124
+ # documents and passes them one by one to the block.
125
+ #
126
+ # block - The block will be called for each document returned from
127
+ # executing the scan query.
128
+ #
129
+ # Yields a document Hash.
130
+ #
131
+ # Examples
132
+ #
133
+ # scan.each_document do |document|
134
+ # document['_id']
135
+ # document['_source']
136
+ # end
137
+ #
138
+ # Returns this Scan instance.
139
+ def each_document( &block )
140
+ each { |hits| hits['hits'].each(&block) }
141
+ end
142
+
143
+ # Internal: Returns the current scroll ID as a String.
144
+ def scroll_id
145
+ return @scroll_id if defined? @scroll_id
146
+
147
+ response = client.get '{/index}{/type}/_search',
148
+ :action => 'search.scan',
149
+ :search_type => 'scan',
150
+ :scroll => scroll,
151
+ :size => size,
152
+ :index => index,
153
+ :type => type,
154
+ :body => query
155
+
156
+ @scroll_id = response.body['_scroll_id']
157
+ end
158
+
159
+ end # Scan
160
+ end # Client
161
+ end # Elastomer
@@ -0,0 +1,85 @@
1
+
2
+ module Elastomer
3
+ class Client
4
+
5
+ # Returns a Template instance.
6
+ def template( name )
7
+ Template.new self, name
8
+ end
9
+
10
+
11
+ class Template
12
+
13
+ # Create a new template client for making API requests that pertain to
14
+ # template management.
15
+ #
16
+ # client - Elastomer::Client used for HTTP requests to the server
17
+ # name - The name of the template as a String
18
+ #
19
+ def initialize( client, name )
20
+ @client = client
21
+ @name = name
22
+ end
23
+
24
+ attr_reader :client, :name
25
+
26
+ # Returns true if the template already exists on the cluster.
27
+ def exists?
28
+ client.cluster.templates.key? name
29
+ end
30
+ alias :exist? :exists?
31
+
32
+ # Get the template from the cluster.
33
+ # See http://www.elasticsearch.org/guide/reference/api/admin-indices-templates/
34
+ #
35
+ # params - Parameters Hash
36
+ #
37
+ # Returns the response body as a Hash
38
+ def get( params = {} )
39
+ response = client.get '/_template/{template}', update_params(params, :action => 'template.get')
40
+ response.body
41
+ end
42
+
43
+ # Create the template on the cluster.
44
+ # See http://www.elasticsearch.org/guide/reference/api/admin-indices-templates/
45
+ #
46
+ # template - The template as a Hash or a JSON encoded String
47
+ # params - Parameters Hash
48
+ #
49
+ # Returns the response body as a Hash
50
+ def create( template, params = {} )
51
+ response = client.put '/_template/{template}', update_params(params, :body => template, :action => 'template.create')
52
+ response.body
53
+ end
54
+
55
+ # Delete the template from the cluster.
56
+ # See http://www.elasticsearch.org/guide/reference/api/admin-indices-templates/
57
+ #
58
+ # params - Parameters Hash
59
+ #
60
+ # Returns the response body as a Hash
61
+ def delete( params = {} )
62
+ response = client.delete '/_template/{template}', update_params(params, :action => 'template.delete')
63
+ response.body
64
+ end
65
+
66
+ # Internal: Add default parameters to the `params` Hash and then apply
67
+ # `overrides` to the params if any are given.
68
+ #
69
+ # params - Parameters Hash
70
+ # overrides - Optional parameter overrides as a Hash
71
+ #
72
+ # Returns a new params Hash.
73
+ def update_params( params, overrides = nil )
74
+ h = defaults.update params
75
+ h.update overrides unless overrides.nil?
76
+ h
77
+ end
78
+
79
+ # Internal: Returns a Hash containing default parameters.
80
+ def defaults
81
+ { :template => name }
82
+ end
83
+ end # Template
84
+ end # Client
85
+ end # Elastomer
@@ -0,0 +1,96 @@
1
+ module Elastomer
2
+ class Client
3
+
4
+ # Provides access to warmer API commands.
5
+ # See http://www.elasticsearch.org/guide/reference/api/admin-indices-warmers/
6
+ #
7
+ # index_name - The name of the index as a String
8
+ # warmer_name - The name of the warmer as a String
9
+ #
10
+ # Returns a Warmer instance.
11
+ def warmer(index_name, warmer_name)
12
+ Warmer.new(self, index_name, warmer_name)
13
+ end
14
+
15
+ class Warmer
16
+
17
+ # Create a new Warmer helper for making warmer API requests.
18
+ #
19
+ # client - Elastomer::Client used for HTTP requests to the server
20
+ # index_name - The name of the index as a String
21
+ # name - The name of the warmer as a String
22
+ def initialize(client, index_name, name)
23
+ @client = client
24
+ @index_name = @client.assert_param_presence(index_name, 'index name')
25
+ @name = @client.assert_param_presence(name, 'warmer name')
26
+ end
27
+
28
+ attr_reader :client, :index_name, :name
29
+
30
+ # Create a warmer.
31
+ # See http://www.elasticsearch.org/guide/reference/api/admin-indices-warmers/
32
+ #
33
+ # query - The query the warmer should run
34
+ # params - Parameters Hash
35
+ #
36
+ # Examples
37
+ #
38
+ # warmer.create(:query => {:match_all => {}})
39
+ #
40
+ # Returns the response body as a Hash
41
+ def create(query, params = {})
42
+ response = client.put '/{index}{/type}/_warmer/{warmer}', defaults.update(params.update(:body => query))
43
+ response.body
44
+ end
45
+
46
+ # Delete a warmer.
47
+ # See http://www.elasticsearch.org/guide/reference/api/admin-indices-warmers/
48
+ #
49
+ # params - Parameters Hash
50
+ #
51
+ # Returns the response body as a Hash
52
+ def delete(params = {})
53
+ response = client.delete '/{index}{/type}/_warmer/{warmer}', defaults.update(params)
54
+ response.body
55
+ end
56
+
57
+ # Get a warmer.
58
+ # See http://www.elasticsearch.org/guide/reference/api/admin-indices-warmers/
59
+ #
60
+ # params - Parameters Hash
61
+ #
62
+ # Returns the response body as a Hash
63
+ def get(params = {})
64
+ response = client.get '/{index}{/type}/_warmer/{warmer}', defaults.update(params)
65
+ response.body
66
+ end
67
+
68
+ # Check whether a warmer exists. Also aliased as exist?
69
+ #
70
+ # Since there is no native warmer exists api, this method executes
71
+ # a get and watches for an IndexWarmerMissingException error.
72
+ #
73
+ # Returns true if the warmer exists, false if not.
74
+ #COMPATIBILITY warmer response differs in ES 1.0
75
+ # ES 1.0: missing warmer returns {} with 200 status
76
+ # ES 0.90: missing warmer returns IndexWarmerMissingException error
77
+ # See https://github.com/elasticsearch/elasticsearch/issues/5155
78
+ def exists?
79
+ response = get
80
+ response != {}
81
+ rescue Elastomer::Client::Error => exception
82
+ if exception.message =~ /IndexWarmerMissingException/
83
+ false
84
+ else
85
+ raise exception
86
+ end
87
+ end
88
+ alias :exist? :exists?
89
+
90
+ # Internal: Returns a Hash containing default parameters.
91
+ def defaults
92
+ {:index => index_name, :warmer => name}
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,7 @@
1
+ require 'time'
2
+
3
+ class Time
4
+ def to_json(ignore = nil)
5
+ %Q["#{self.iso8601}"]
6
+ end
7
+ end
@@ -0,0 +1,51 @@
1
+ module Elastomer
2
+ module Middleware
3
+ # Request middleware that encodes the body as JSON.
4
+ #
5
+ # Processes only requests with matching Content-type or those without a type.
6
+ # If a request doesn't have a type but has a body, it sets the Content-type
7
+ # to JSON MIME-type.
8
+ #
9
+ # Doesn't try to encode bodies that already are in string form.
10
+ class EncodeJson < Faraday::Middleware
11
+ CONTENT_TYPE = 'Content-Type'.freeze
12
+ MIME_TYPE = 'application/json'.freeze
13
+
14
+ def call(env)
15
+ match_content_type(env) do |data|
16
+ env[:body] = encode data
17
+ end
18
+ @app.call env
19
+ end
20
+
21
+ def encode(data)
22
+ MultiJson.dump data
23
+ end
24
+
25
+ def match_content_type(env)
26
+ if process_request?(env)
27
+ env[:request_headers][CONTENT_TYPE] ||= MIME_TYPE
28
+ yield env[:body] unless env[:body].respond_to?(:to_str)
29
+ end
30
+ end
31
+
32
+ def process_request?(env)
33
+ type = request_type(env)
34
+ has_body?(env) and (type.empty? or type == MIME_TYPE)
35
+ end
36
+
37
+ def has_body?(env)
38
+ body = env[:body] and !(body.respond_to?(:to_str) and body.empty?)
39
+ end
40
+
41
+ def request_type(env)
42
+ type = env[:request_headers][CONTENT_TYPE].to_s
43
+ type = type.split(';', 2).first if type.index(';')
44
+ type
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ Faraday::Request.register_middleware \
51
+ :encode_json => ::Elastomer::Middleware::EncodeJson