stretch 0.0.0 → 0.1.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/.gitignore CHANGED
@@ -6,6 +6,7 @@
6
6
  Gemfile.lock
7
7
  InstalledFiles
8
8
  _yardoc
9
+ bin/
9
10
  coverage
10
11
  doc/
11
12
  lib/bundler/man
@@ -14,4 +15,5 @@ rdoc
14
15
  spec/reports
15
16
  test/tmp
16
17
  test/version_tmp
18
+ vendor/gems
17
19
  tmp
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ script: "./script/test"
3
+ gemfile: "this/does/not/exist"
4
+ rvm:
5
+ - "1.8.7"
6
+ - "1.9.3"
7
+ - "2.0.0"
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,14 @@
1
+ # Contributing Guidelines
2
+
3
+ Tests are run with `script/test`.
4
+
5
+ Test against the following Ruby versions:
6
+
7
+ * 1.8.7
8
+ * 1.9.3
9
+ * 2.0.0
10
+
11
+ Always work on a fork, on a feature branch.
12
+
13
+ Submit Pull Requests, with new tests for any changes.
14
+ Make sure the tests pass.
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # Stretch
2
2
 
3
- Shhh -- a secret!
3
+ [![Build Status](https://travis-ci.org/wfarr/stretch.png?branch=master)](https://travis-ci.org/wfarr/stretch)
4
+ [![Code Climate Status](https://codeclimate.com/github/wfarr/stretch.png)](https://codeclimate.com/github/wfarr/stretch)
5
+
6
+ Elasticsearch client library written for people who like understandable
7
+ documentation and understandable code.
4
8
 
5
9
  ## Installation
6
10
 
@@ -18,12 +22,39 @@ Or install it yourself as:
18
22
 
19
23
  ## Usage
20
24
 
21
- You obviously can't use this yet.
25
+ ### Establishing a connection:
26
+
27
+ ``` ruby
28
+ $stretch = Stretch::Client.new :url => "http://127.0.0.1:9200/"
29
+ ```
30
+
31
+ ### Cluster and Index Health
32
+
33
+ ``` ruby
34
+ $stretch.cluster.health :timeout => '10s'
35
+ $stretch.index('tweets').health :wait_for_status => 'green'
36
+ ```
37
+
38
+ ### Cluster State
39
+
40
+ ``` ruby
41
+ $stretch.cluster.state
42
+ $stretch.cluster.state :filter_nodes => true
43
+ ```
44
+
45
+ ### Cluster and Index Settings
46
+
47
+ ``` ruby
48
+ $stretch.cluster.settings :persistent => {
49
+ "cluster.routing.allocation.node_concurrent_recoveries" => 4
50
+ }
51
+
52
+ $stretch.index('foo').settings :index => { :number_of_replicas => 2 }
53
+ ```
22
54
 
23
- ## Contributing
55
+ ### Opening and Closing Indices
24
56
 
25
- 1. Fork it
26
- 2. Create your feature branch (`git checkout -b my-new-feature`)
27
- 3. Commit your changes (`git commit -am 'Add some feature'`)
28
- 4. Push to the branch (`git push origin my-new-feature`)
29
- 5. Create new Pull Request
57
+ ``` ruby
58
+ $stretch.index('foo').open!
59
+ $stretch.index('bar').close!
60
+ ```
data/lib/stretch.rb CHANGED
@@ -1,5 +1,7 @@
1
+ require "stretch/client"
1
2
  require "stretch/version"
2
3
 
3
4
  module Stretch
4
- # Your code goes here...
5
+ class InvalidScope < StandardError; end
6
+ class UnsupportedRequestMethod < StandardError; end
5
7
  end
@@ -0,0 +1,83 @@
1
+ require "stretch/connection"
2
+ require "stretch/uri_builder"
3
+
4
+ module Stretch
5
+ class Client
6
+ attr_reader :connection, :scope
7
+
8
+ def initialize options = {}
9
+ self.tap do
10
+ @scope = {
11
+ :cluster => false,
12
+ :index => nil
13
+ }
14
+
15
+ @connection = Stretch::Connection.new options
16
+ end
17
+ end
18
+
19
+ # Chainable methods
20
+ def cluster
21
+ self.tap do
22
+ scope[:cluster] = true
23
+ scope[:index] = nil
24
+ end
25
+ end
26
+
27
+ def index name
28
+ self.tap do
29
+ scope[:cluster] = false
30
+ scope[:index] = name
31
+ end
32
+ end
33
+
34
+ # End points
35
+ def health options = {}
36
+ with_scopes :cluster, :index do
37
+ connection.get build_path("/health"), options
38
+ end
39
+ end
40
+
41
+ def state options = {}
42
+ with_scopes :cluster do
43
+ connection.get build_path("/state"), options
44
+ end
45
+ end
46
+
47
+ def settings options = {}
48
+ with_scopes :cluster, :index do
49
+ if options.any?
50
+ connection.put build_path("/settings"), options
51
+ else
52
+ connection.get build_path("/settings")
53
+ end
54
+ end
55
+ end
56
+
57
+ def open!
58
+ with_scopes :index do
59
+ connection.post build_path("/_open")
60
+ end
61
+ end
62
+
63
+ def close!
64
+ with_scopes :index do
65
+ connection.post build_path("/_close")
66
+ end
67
+ end
68
+
69
+ private
70
+ def build_path path
71
+ Stretch::URIBuilder.build_from_scope scope, path
72
+ end
73
+
74
+ def with_scopes *scopes, &block
75
+ if scopes.any? {|s| scope.has_key?(s) && scope[s] }
76
+ yield
77
+ else
78
+ raise InvalidScope,
79
+ "Requires one of the following scopes: #{scopes.inspect}. #{scope.inspect} given."
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,67 @@
1
+ require "faraday"
2
+ require "multi_json"
3
+
4
+ module Stretch
5
+ class Connection
6
+ attr_reader :connection
7
+
8
+ REQUEST_METHODS = [ :get, :post, :put, :delete ].freeze
9
+
10
+ def initialize options = {}
11
+ @connection = Faraday.new(options)
12
+ end
13
+
14
+ def get path, options = {}
15
+ request :get, path, options
16
+ end
17
+
18
+ def post path, options = {}
19
+ request :post, path, options
20
+ end
21
+
22
+ def put path, options = {}
23
+ request :put, path, options
24
+ end
25
+
26
+ def delete path, options = {}
27
+ request :delete, path, options
28
+ end
29
+
30
+ private
31
+ def request method, path, options = {}
32
+ validate_request_method method
33
+
34
+ response = connection.send(method) do |request|
35
+ request.headers["Accept"] = "application/json"
36
+ request.path = path
37
+
38
+ case method
39
+ when :get
40
+ options.each { |k,v| request.params[k] = v }
41
+ when :post, :put
42
+ request.body = MultiJson.dump(options)
43
+ end
44
+ end
45
+
46
+ handle_response response
47
+ end
48
+
49
+ def validate_request_method method
50
+ unless REQUEST_METHODS.member? method
51
+ raise Stretch::UnsupportedRequestMethod, "#{method} is not supported!"
52
+ end
53
+ end
54
+
55
+ def handle_response response
56
+ if response.success?
57
+ if response.body.empty?
58
+ request :get, path
59
+ else
60
+ MultiJson.load response.body
61
+ end
62
+ else
63
+ response.error!
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,13 @@
1
+ module Stretch
2
+ class URIBuilder
3
+ def self.build_from_scope scope, path
4
+ path.gsub!(/\A\//, '')
5
+
6
+ if scope[:cluster]
7
+ "/_cluster/#{path}"
8
+ elsif scope[:index]
9
+ "/#{scope[:index]}/#{path}"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module Stretch
2
- VERSION = "0.0.0"
2
+ VERSION = "0.1.0"
3
3
  end
data/script/bootstrap ADDED
@@ -0,0 +1,5 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ bundle install --path .bundle --binstubs .bundle/binstubs "$@"
data/script/test ADDED
@@ -0,0 +1,11 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ root=$(cd "$(dirname $0)"/.. && pwd)
6
+
7
+ echo "Bundling..."
8
+ script/bootstrap
9
+
10
+ ruby -I"${root}/.bundle" -I"${root}/test" -e \
11
+ "(ARGV.empty? ? Dir['${root}/test/**/*_test.rb'] : ARGV).each { |f| load f }"
data/stretch.gemspec CHANGED
@@ -8,9 +8,11 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Stretch::VERSION
9
9
  spec.authors = ["Will Farrington"]
10
10
  spec.email = ["wfarr@github.com"]
11
- spec.description = %q{Shh, it's a secret}
12
- spec.summary = %q{Still seriously a secret}
13
- spec.homepage = ""
11
+ spec.description = %q{An Elasticsearch client library}
12
+ spec.summary = %q{It's not anywhere near complete at this time, but
13
+ the code is pretty all right allegedly.
14
+ }
15
+ spec.homepage = "https://github.com/wfarr/stretch"
14
16
  spec.license = "MIT"
15
17
 
16
18
  spec.files = `git ls-files`.split($/)
@@ -18,6 +20,11 @@ Gem::Specification.new do |spec|
18
20
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
21
  spec.require_paths = ["lib"]
20
22
 
21
- spec.add_development_dependency "bundler", "~> 1.3"
23
+ spec.add_dependency "faraday", "~> 0.8.7"
24
+ spec.add_dependency "multi_json", "~> 1.7.2"
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.2"
27
+ spec.add_development_dependency "minitest", "~> 4.0"
28
+ spec.add_development_dependency "pry"
22
29
  spec.add_development_dependency "rake"
23
30
  end
@@ -0,0 +1,153 @@
1
+ require "test_helper"
2
+
3
+ require "stretch/client"
4
+
5
+ describe Stretch::Client do
6
+ let(:instance) { described_class.new }
7
+ let(:connection) { MiniTest::Mock.new }
8
+
9
+ describe ".new" do
10
+ describe "scope defaults" do
11
+ it "index to nil" do
12
+ assert_nil instance.scope[:index]
13
+ end
14
+
15
+ it "cluster to false" do
16
+ refute instance.scope[:cluster]
17
+ end
18
+ end
19
+ end
20
+
21
+ it "can chain index" do
22
+ assert instance.index("foo").is_a?(Stretch::Client)
23
+ assert_equal "foo", instance.scope[:index]
24
+ end
25
+
26
+ it "can chain cluster" do
27
+ assert instance.cluster.is_a?(Stretch::Client)
28
+ assert instance.scope[:cluster]
29
+ end
30
+
31
+ describe "#health" do
32
+ it "requires either a cluster scope or an index scope" do
33
+ instance.stub :scope, { :cluster => false, :index => nil } do
34
+ assert_raises Stretch::InvalidScope do
35
+ instance.health
36
+ end
37
+ end
38
+ end
39
+
40
+ it "requests cluster health if the scope is cluster" do
41
+ instance.stub :connection, connection do
42
+ connection.expect :get, { "status" => "ok" }, ["/_cluster/health", {}]
43
+ instance.cluster.health
44
+
45
+ connection.verify
46
+ end
47
+ end
48
+
49
+ it "requests index health if the scope is an index" do
50
+ instance.stub :connection, connection do
51
+ connection.expect :get, { "status" => "ok" }, ["/foo/health", {}]
52
+ instance.index("foo").health
53
+
54
+ connection.verify
55
+ end
56
+ end
57
+ end
58
+
59
+ describe "#state" do
60
+ it "requires a cluster scope" do
61
+ instance.stub :scope, { :cluster => false } do
62
+ assert_raises Stretch::InvalidScope do
63
+ instance.state
64
+ end
65
+ end
66
+ end
67
+
68
+ it "can return the state of a cluster" do
69
+ instance.connection.stub :get, { "status" => "ok" } do
70
+ assert_equal "ok", instance.cluster.state["status"]
71
+ end
72
+ end
73
+ end
74
+
75
+ describe "#settings" do
76
+ it "requires either a cluster scope or an index scope" do
77
+ instance.stub :scope, { :cluster => false, :index => nil } do
78
+ assert_raises Stretch::InvalidScope do
79
+ instance.settings
80
+ end
81
+ end
82
+ end
83
+
84
+ describe "no options given" do
85
+ it "performs a get request for the settings" do
86
+ response = { "persistent" => { "foo" => 1 } }
87
+
88
+ instance.stub :connection, connection do
89
+ connection.expect :get, response, ["/_cluster/settings"]
90
+ assert_equal 1, instance.cluster.settings["persistent"]["foo"]
91
+
92
+ connection.verify
93
+ end
94
+ end
95
+ end
96
+
97
+ describe "options given" do
98
+ it "performs a put request with options for the settings" do
99
+ params = { :index => { :refresh_interval => -1 } }
100
+ response = { "index" => {"refresh_interval" => -1} }
101
+
102
+ instance.stub :connection, connection do
103
+ connection.expect :put, response, ["/foo/settings", params]
104
+ assert_equal -1, instance.index("foo").settings(params)["index"]["refresh_interval"]
105
+
106
+ connection.verify
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ describe "#open!" do
113
+ it "requires the index scope" do
114
+ instance.stub :scope, { :cluster => true, :index => nil } do
115
+ assert_raises Stretch::InvalidScope do
116
+ instance.open!
117
+ end
118
+ end
119
+ end
120
+
121
+ it "performs a post request to open the index" do
122
+ response = { "ok" => true, "acknowledged" => true }
123
+
124
+ instance.stub :connection, connection do
125
+ connection.expect :post, response, ["/foo/_open"]
126
+ assert_equal true, instance.index("foo").open!["ok"]
127
+
128
+ connection.verify
129
+ end
130
+ end
131
+ end
132
+
133
+ describe "#close!" do
134
+ it "requires the index scope" do
135
+ instance.stub :scope, { :cluster => true, :index => nil } do
136
+ assert_raises Stretch::InvalidScope do
137
+ instance.close!
138
+ end
139
+ end
140
+ end
141
+
142
+ it "performs a post request to close the index" do
143
+ response = { "ok" => true, "acknowledged" => true }
144
+
145
+ instance.stub :connection, connection do
146
+ connection.expect :post, response, ["/foo/_close"]
147
+ assert_equal true, instance.index("foo").close!["ok"]
148
+
149
+ connection.verify
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,42 @@
1
+ require "test_helper"
2
+
3
+ require "stretch/connection"
4
+
5
+ describe Stretch::Connection do
6
+ let(:instance) { described_class.new }
7
+ let(:response) do
8
+ Struct.new :response do
9
+ def body
10
+ MultiJson.dump({ "status" => "ok" })
11
+ end
12
+
13
+ def success?
14
+ true
15
+ end
16
+ end.new
17
+ end
18
+
19
+ it "accepts get requests" do
20
+ instance.connection.stub :get, response do
21
+ instance.get "/foo"
22
+ end
23
+ end
24
+
25
+ it "accepts post requests" do
26
+ instance.connection.stub :post, response do
27
+ instance.post "/foo"
28
+ end
29
+ end
30
+
31
+ it "accepts put requests" do
32
+ instance.connection.stub :put, response do
33
+ instance.put "/foo"
34
+ end
35
+ end
36
+
37
+ it "accepts delete requests" do
38
+ instance.connection.stub :delete, response do
39
+ instance.delete "/foo"
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,9 @@
1
+ require "test_helper"
2
+
3
+ require "stretch"
4
+
5
+ describe Stretch do
6
+ it "is a defined module name" do
7
+ assert defined?(Stretch)
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+
4
+ require "minitest/spec"
5
+ require "minitest/autorun"
6
+
7
+ class MiniTest::Spec
8
+ def described_class
9
+ @described_class ||= self.class.ancestors.select { |c|
10
+ c.respond_to? :desc
11
+ }[-2].desc
12
+ end
13
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stretch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,40 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-12 00:00:00.000000000 Z
12
+ date: 2013-04-14 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: faraday
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.8.7
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.8.7
30
+ - !ruby/object:Gem::Dependency
31
+ name: multi_json
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 1.7.2
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.7.2
14
46
  - !ruby/object:Gem::Dependency
15
47
  name: bundler
16
48
  requirement: !ruby/object:Gem::Requirement
@@ -18,7 +50,23 @@ dependencies:
18
50
  requirements:
19
51
  - - ~>
20
52
  - !ruby/object:Gem::Version
21
- version: '1.3'
53
+ version: '1.2'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.2'
62
+ - !ruby/object:Gem::Dependency
63
+ name: minitest
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '4.0'
22
70
  type: :development
23
71
  prerelease: false
24
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +74,23 @@ dependencies:
26
74
  requirements:
27
75
  - - ~>
28
76
  - !ruby/object:Gem::Version
29
- version: '1.3'
77
+ version: '4.0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: pry
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'
30
94
  - !ruby/object:Gem::Dependency
31
95
  name: rake
32
96
  requirement: !ruby/object:Gem::Requirement
@@ -43,7 +107,7 @@ dependencies:
43
107
  - - ! '>='
44
108
  - !ruby/object:Gem::Version
45
109
  version: '0'
46
- description: Shh, it's a secret
110
+ description: An Elasticsearch client library
47
111
  email:
48
112
  - wfarr@github.com
49
113
  executables: []
@@ -51,14 +115,25 @@ extensions: []
51
115
  extra_rdoc_files: []
52
116
  files:
53
117
  - .gitignore
118
+ - .travis.yml
119
+ - CONTRIBUTING.md
54
120
  - Gemfile
55
121
  - LICENSE.txt
56
122
  - README.md
57
123
  - Rakefile
58
124
  - lib/stretch.rb
125
+ - lib/stretch/client.rb
126
+ - lib/stretch/connection.rb
127
+ - lib/stretch/uri_builder.rb
59
128
  - lib/stretch/version.rb
129
+ - script/bootstrap
130
+ - script/test
60
131
  - stretch.gemspec
61
- homepage: ''
132
+ - test/stretch/client_test.rb
133
+ - test/stretch/connection_test.rb
134
+ - test/stretch_test.rb
135
+ - test/test_helper.rb
136
+ homepage: https://github.com/wfarr/stretch
62
137
  licenses:
63
138
  - MIT
64
139
  post_install_message:
@@ -71,16 +146,27 @@ required_ruby_version: !ruby/object:Gem::Requirement
71
146
  - - ! '>='
72
147
  - !ruby/object:Gem::Version
73
148
  version: '0'
149
+ segments:
150
+ - 0
151
+ hash: 3712832259908765
74
152
  required_rubygems_version: !ruby/object:Gem::Requirement
75
153
  none: false
76
154
  requirements:
77
155
  - - ! '>='
78
156
  - !ruby/object:Gem::Version
79
157
  version: '0'
158
+ segments:
159
+ - 0
160
+ hash: 3712832259908765
80
161
  requirements: []
81
162
  rubyforge_project:
82
163
  rubygems_version: 1.8.23
83
164
  signing_key:
84
165
  specification_version: 3
85
- summary: Still seriously a secret
86
- test_files: []
166
+ summary: It's not anywhere near complete at this time, but the code is pretty all
167
+ right allegedly.
168
+ test_files:
169
+ - test/stretch/client_test.rb
170
+ - test/stretch/connection_test.rb
171
+ - test/stretch_test.rb
172
+ - test/test_helper.rb