flying-sphinx 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +11 -35
- data/Appraisals +23 -21
- data/Gemfile +5 -10
- data/README.textile +5 -3
- data/flying-sphinx.gemspec +7 -3
- data/lib/flying_sphinx.rb +8 -2
- data/lib/flying_sphinx/action.rb +1 -1
- data/lib/flying_sphinx/api.rb +6 -20
- data/lib/flying_sphinx/cli.rb +3 -1
- data/lib/flying_sphinx/configuration.rb +1 -1
- data/lib/flying_sphinx/configuration_options.rb +12 -15
- data/lib/flying_sphinx/configurer.rb +62 -0
- data/lib/flying_sphinx/controller.rb +26 -27
- data/lib/flying_sphinx/request/hmac.rb +20 -0
- data/lib/flying_sphinx/response/json.rb +2 -0
- data/lib/flying_sphinx/setting_files.rb +1 -1
- data/lib/flying_sphinx/version.rb +1 -1
- data/spec/acceptance/configuring_spec.rb +34 -0
- data/spec/acceptance/get_info_spec.rb +5 -4
- data/spec/acceptance/start_or_stop_sphinx_spec.rb +12 -2
- data/spec/flying_sphinx/action_spec.rb +1 -1
- data/spec/flying_sphinx/api_spec.rb +2 -22
- data/spec/flying_sphinx/configuration_spec.rb +1 -1
- data/spec/flying_sphinx/controller_spec.rb +33 -19
- data/spec/flying_sphinx/setting_files_spec.rb +16 -16
- data/spec/spec_helper.rb +1 -0
- data/spec/support/hmac.rb +23 -0
- data/spec/support/multipart.rb +56 -0
- data/spec/support/successful_action.rb +7 -1
- metadata +108 -73
- data/gemfiles/rails_2.3.gemfile +0 -21
- data/gemfiles/rails_3.0.gemfile +0 -21
- data/gemfiles/rails_3.2.gemfile +0 -18
- data/gemfiles/rails_4.0.gemfile +0 -18
- data/lib/flying_sphinx/gzipped_hash.rb +0 -36
@@ -0,0 +1,20 @@
|
|
1
|
+
class FlyingSphinx::Request::HMAC < Faraday::Middleware
|
2
|
+
def initialize(app, identifier, api_key, service)
|
3
|
+
super app
|
4
|
+
|
5
|
+
@identifier = identifier
|
6
|
+
@api_key = api_key
|
7
|
+
@service = service
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(environment)
|
11
|
+
Ey::Hmac.sign! environment, identifier, api_key,
|
12
|
+
:adapter => Ey::Hmac::Adapter::Faraday, :service => service
|
13
|
+
|
14
|
+
app.call environment
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :app, :identifier, :api_key, :service
|
20
|
+
end
|
@@ -10,7 +10,7 @@ class FlyingSphinx::SettingFiles
|
|
10
10
|
hash = {}
|
11
11
|
|
12
12
|
each_file_for_setting do |setting, file|
|
13
|
-
hash["#{setting}
|
13
|
+
hash["#{setting}/#{File.basename(file)}"] = File.read(file)
|
14
14
|
end
|
15
15
|
|
16
16
|
hash['extra'] = hash.keys.join(';')
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
describe 'Configuring Sphinx' do
|
5
|
+
let(:cli) { FlyingSphinx::CLI.new 'configure' }
|
6
|
+
let(:translator) { double 'Translator', :sphinx_indices => [index],
|
7
|
+
:sphinx_configuration => 'searchd { }' }
|
8
|
+
let(:index) { double 'Index' }
|
9
|
+
|
10
|
+
before :each do
|
11
|
+
allow(FlyingSphinx).to receive(:translator).and_return(translator)
|
12
|
+
|
13
|
+
stub_hmac_request(:post, 'https://flying-sphinx.com/api/my/v5/perform').
|
14
|
+
to_return(:body => '{"id":953, "status":"OK"}')
|
15
|
+
stub_hmac_request(:get, "https://flying-sphinx.com/api/my/v5/presignature").
|
16
|
+
to_return(
|
17
|
+
:body => '{"url":"https://foo","path":"bar","fields":{},"status":"OK"}'
|
18
|
+
)
|
19
|
+
stub_request(:post, "https://foo/").to_return(:status => 200)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'sends the configuration to the server' do
|
23
|
+
SuccessfulAction.new(953).matches? lambda { cli.run }
|
24
|
+
|
25
|
+
expect(
|
26
|
+
a_hmac_request(:post, 'https://flying-sphinx.com/api/my/v5/perform').
|
27
|
+
with { |request| CGI::parse(request.body)["action"] == ["configure"] }
|
28
|
+
).to have_been_made
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'handles the full request successfully' do
|
32
|
+
expect { cli.run }.to be_successful_with 953
|
33
|
+
end
|
34
|
+
end
|
@@ -4,10 +4,11 @@ describe 'Requesting customer information' do
|
|
4
4
|
let(:configuration) { FlyingSphinx::Configuration.new 'foo', 'bar' }
|
5
5
|
|
6
6
|
before :each do
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
stub_hmac_request(:get, 'https://flying-sphinx.com/api/my/v5/app').
|
8
|
+
to_return(
|
9
|
+
:status => 200,
|
10
|
+
:body => '{"server":"my.sphinx.server","port":9307}'
|
11
|
+
)
|
11
12
|
end
|
12
13
|
|
13
14
|
it { expect(configuration.host).to eq('my.sphinx.server') }
|
@@ -4,12 +4,17 @@ describe 'Starting Sphinx' do
|
|
4
4
|
let(:cli) { FlyingSphinx::CLI.new 'start' }
|
5
5
|
|
6
6
|
before :each do
|
7
|
-
|
7
|
+
stub_hmac_request(:post, 'https://flying-sphinx.com/api/my/v5/perform').
|
8
8
|
to_return(:status => 200, :body => '{"id":429, "status":"OK"}')
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'makes the request to the server', :retry => 3 do
|
12
12
|
expect { cli.run }.to be_successful_with 429
|
13
|
+
|
14
|
+
expect(
|
15
|
+
a_hmac_request(:post, 'https://flying-sphinx.com/api/my/v5/perform').
|
16
|
+
with(:body => {:action => 'start'})
|
17
|
+
).to have_been_made
|
13
18
|
end
|
14
19
|
end
|
15
20
|
|
@@ -17,11 +22,16 @@ describe 'Stopping Sphinx', :retry => 3 do
|
|
17
22
|
let(:cli) { FlyingSphinx::CLI.new 'stop' }
|
18
23
|
|
19
24
|
before :each do
|
20
|
-
stub_request(:post, 'https://flying-sphinx.com/api/my/
|
25
|
+
stub_request(:post, 'https://flying-sphinx.com/api/my/v5/perform').
|
21
26
|
to_return(:status => 200, :body => '{"id":537, "status":"OK"}')
|
22
27
|
end
|
23
28
|
|
24
29
|
it 'makes the request to the server', :retry => 3 do
|
25
30
|
expect { cli.run }.to be_successful_with 537
|
31
|
+
|
32
|
+
expect(
|
33
|
+
a_hmac_request(:post, 'https://flying-sphinx.com/api/my/v5/perform').
|
34
|
+
with(:body => {:action => 'stop'})
|
35
|
+
).to have_been_made
|
26
36
|
end
|
27
37
|
end
|
@@ -6,7 +6,7 @@ describe FlyingSphinx::Action do
|
|
6
6
|
let(:socket) { double 'socket', :connect => true, :disconnect => true,
|
7
7
|
:subscribe => true, :[] => channel, :connected => true }
|
8
8
|
let(:channel) { double 'channel', :bind => true }
|
9
|
-
let(:response) {
|
9
|
+
let(:response) { {'status' => 'OK', 'id' => 748} }
|
10
10
|
let(:logger) { double 'logger', :debug => true }
|
11
11
|
|
12
12
|
before :each do
|
@@ -18,8 +18,6 @@ describe FlyingSphinx::API do
|
|
18
18
|
it "sets up a connection with the appropriate headers" do
|
19
19
|
faraday.should_receive(:new) do |options|
|
20
20
|
options[:headers].should == {
|
21
|
-
'Accept' => 'application/vnd.flying-sphinx-v4+json',
|
22
|
-
'X-Flying-Sphinx-Token' => 'foo:bar',
|
23
21
|
'X-Flying-Sphinx-Version' => FlyingSphinx::Version
|
24
22
|
}
|
25
23
|
|
@@ -52,7 +50,7 @@ describe FlyingSphinx::API do
|
|
52
50
|
|
53
51
|
it "sends the GET request with the given path and data" do
|
54
52
|
request.should_receive(:url).
|
55
|
-
with('/api/my/
|
53
|
+
with('/api/my/v5/resource', 'param' => 'value')
|
56
54
|
|
57
55
|
send_request
|
58
56
|
end
|
@@ -69,25 +67,7 @@ describe FlyingSphinx::API do
|
|
69
67
|
|
70
68
|
it "sends the POST request with the given path and data" do
|
71
69
|
connection.should_receive(:post).
|
72
|
-
with('/api/my/
|
73
|
-
and_return(response)
|
74
|
-
|
75
|
-
send_request
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
describe '#put' do
|
80
|
-
let(:send_request) { api.put '/resource', 'param' => 'value' }
|
81
|
-
|
82
|
-
before :each do
|
83
|
-
connection.stub(:put => response)
|
84
|
-
end
|
85
|
-
|
86
|
-
it_should_behave_like 'an API call'
|
87
|
-
|
88
|
-
it "sends the PUT request with the given path and data" do
|
89
|
-
connection.should_receive(:put).
|
90
|
-
with('/api/my/app/resource', 'param' => 'value').
|
70
|
+
with('/api/my/v5/resource', 'param' => 'value').
|
91
71
|
and_return(response)
|
92
72
|
|
93
73
|
send_request
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe FlyingSphinx::Configuration do
|
4
|
-
let(:api) { double 'FlyingSphinx::API', :get =>
|
4
|
+
let(:api) { double 'FlyingSphinx::API', :get => body }
|
5
5
|
let(:body) { {'server' => 'foo.bar.com', 'port' => 9319} }
|
6
6
|
let(:api_key) { 'foo-bar-baz' }
|
7
7
|
let(:identifier) { 'my-identifier' }
|
@@ -2,11 +2,12 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe FlyingSphinx::Controller do
|
4
4
|
let(:controller) { FlyingSphinx::Controller.new api }
|
5
|
-
let(:api) { double 'API', :identifier => 'foo', :put => true
|
5
|
+
let(:api) { double 'API', :identifier => 'foo', :put => true,
|
6
|
+
:get => {"path" => "/foo", "url" => "https://confserver", "status" => "OK"} }
|
6
7
|
let(:action_class) { double }
|
7
8
|
let(:configuration) { double 'TS Configuration' }
|
8
|
-
let(:setting_files) { double :to_hash => {'extra' => 'wordforms
|
9
|
-
'wordforms
|
9
|
+
let(:setting_files) { double :to_hash => {'extra' => 'wordforms/txt.txt',
|
10
|
+
'wordforms/txt.txt' => 'something'} }
|
10
11
|
let(:translator) { double :sphinx_configuration => 'indexer ...' }
|
11
12
|
|
12
13
|
before :each do
|
@@ -20,38 +21,51 @@ describe FlyingSphinx::Controller do
|
|
20
21
|
|
21
22
|
stub_const 'FlyingSphinx::SettingFiles', double(:new => setting_files)
|
22
23
|
FlyingSphinx.stub :translator => translator
|
23
|
-
end
|
24
24
|
|
25
|
-
|
26
|
-
io = StringIO.new contents, 'rb'
|
27
|
-
reader = Zlib::GzipReader.new io
|
28
|
-
reader.read
|
25
|
+
stub_request(:post, "https://confserver").to_return(:status => 200)
|
29
26
|
end
|
30
27
|
|
31
28
|
describe 'configure' do
|
32
29
|
it 'sends data to the server' do
|
33
|
-
api.should_receive(:
|
30
|
+
api.should_receive(:post)
|
34
31
|
|
35
32
|
controller.configure
|
36
33
|
end
|
37
34
|
|
38
|
-
it 'sends through gzipped configuration
|
39
|
-
api.
|
40
|
-
|
41
|
-
|
42
|
-
ungzip(options[:configuration]['sphinx'].read).should == 'indexer ...'
|
43
|
-
ungzip(options[:configuration]['wordforms:txt.txt'].read).should == 'something'
|
44
|
-
end
|
35
|
+
it 'sends through gzipped configuration archive' do
|
36
|
+
expect(api).to receive(:post).with '/perform',
|
37
|
+
:action => 'configure',
|
38
|
+
:path => '/foo'
|
45
39
|
|
46
40
|
controller.configure
|
41
|
+
|
42
|
+
expect(
|
43
|
+
a_multipart_request(:post, 'https://confserver').
|
44
|
+
with_file { |contents|
|
45
|
+
reader = GZippedTar::Reader.new contents
|
46
|
+
|
47
|
+
reader.read("sphinx/raw.conf") == "indexer ..." &&
|
48
|
+
reader.read("sphinx/version.txt") == "2.2.3" &&
|
49
|
+
reader.read("wordforms/txt.txt") == "something"
|
50
|
+
}
|
51
|
+
).to have_been_made
|
47
52
|
end
|
48
53
|
|
49
54
|
it 'sends through file if provided' do
|
50
|
-
api.
|
51
|
-
:
|
52
|
-
:
|
55
|
+
expect(api).to receive(:post).with '/perform',
|
56
|
+
:action => 'configure',
|
57
|
+
:path => '/foo'
|
53
58
|
|
54
59
|
controller.configure 'searchd ...'
|
60
|
+
|
61
|
+
expect(
|
62
|
+
a_multipart_request(:post, 'https://confserver').
|
63
|
+
with_file { |contents|
|
64
|
+
reader = GZippedTar::Reader.new contents
|
65
|
+
|
66
|
+
reader.read("sphinx/raw.conf") == "searchd ..."
|
67
|
+
}
|
68
|
+
).to have_been_made
|
55
69
|
end
|
56
70
|
end
|
57
71
|
end
|
@@ -18,12 +18,12 @@ describe FlyingSphinx::SettingFiles do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
[:stopwords, :wordforms, :exceptions].each do |setting|
|
21
|
-
it "
|
21
|
+
it "collects #{setting} files from indices" do
|
22
22
|
indices << index_double(setting => '/my/file/foo.txt')
|
23
23
|
|
24
24
|
files.to_hash.should == {
|
25
|
-
"#{setting}
|
26
|
-
'extra' => "#{setting}
|
25
|
+
"#{setting}/foo.txt" => 'blah',
|
26
|
+
'extra' => "#{setting}/foo.txt"
|
27
27
|
}
|
28
28
|
end
|
29
29
|
|
@@ -32,8 +32,8 @@ describe FlyingSphinx::SettingFiles do
|
|
32
32
|
indices << index_double(setting => '/my/file/foo.txt')
|
33
33
|
|
34
34
|
files.to_hash.should == {
|
35
|
-
"#{setting}
|
36
|
-
'extra' => "#{setting}
|
35
|
+
"#{setting}/foo.txt" => 'blah',
|
36
|
+
'extra' => "#{setting}/foo.txt"
|
37
37
|
}
|
38
38
|
end
|
39
39
|
|
@@ -41,22 +41,22 @@ describe FlyingSphinx::SettingFiles do
|
|
41
41
|
indices << index_double(
|
42
42
|
setting => '/my/file/foo.txt /my/file/bar.txt')
|
43
43
|
|
44
|
-
files.to_hash["#{setting}
|
45
|
-
files.to_hash["#{setting}
|
44
|
+
files.to_hash["#{setting}/foo.txt"].should == 'blah'
|
45
|
+
files.to_hash["#{setting}/bar.txt"].should == 'blah'
|
46
46
|
files.to_hash['extra'].split(';').should =~ [
|
47
|
-
"#{setting}
|
47
|
+
"#{setting}/foo.txt", "#{setting}/bar.txt"
|
48
48
|
]
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
52
|
[:mysql_ssl_cert, :mysql_ssl_key, :mysql_ssl_ca].each do |setting|
|
53
|
-
it "
|
53
|
+
it "collects #{setting} files from sources" do
|
54
54
|
indices << index_double(:sources => [
|
55
55
|
source_double(setting => '/my/file/foo.txt')])
|
56
56
|
|
57
57
|
files.to_hash.should == {
|
58
|
-
"#{setting}
|
59
|
-
'extra' => "#{setting}
|
58
|
+
"#{setting}/foo.txt" => 'blah',
|
59
|
+
'extra' => "#{setting}/foo.txt"
|
60
60
|
}
|
61
61
|
end
|
62
62
|
|
@@ -67,8 +67,8 @@ describe FlyingSphinx::SettingFiles do
|
|
67
67
|
source_double(setting => '/my/file/foo.txt')])
|
68
68
|
|
69
69
|
files.to_hash.should == {
|
70
|
-
"#{setting}
|
71
|
-
'extra' => "#{setting}
|
70
|
+
"#{setting}/foo.txt" => 'blah',
|
71
|
+
'extra' => "#{setting}/foo.txt"
|
72
72
|
}
|
73
73
|
end
|
74
74
|
|
@@ -76,10 +76,10 @@ describe FlyingSphinx::SettingFiles do
|
|
76
76
|
indices << index_double(:sources => [
|
77
77
|
source_double(setting => '/my/file/foo.txt /my/file/bar.txt')])
|
78
78
|
|
79
|
-
files.to_hash["#{setting}
|
80
|
-
files.to_hash["#{setting}
|
79
|
+
files.to_hash["#{setting}/foo.txt"].should == 'blah'
|
80
|
+
files.to_hash["#{setting}/bar.txt"].should == 'blah'
|
81
81
|
files.to_hash['extra'].split(';').should =~ [
|
82
|
-
"#{setting}
|
82
|
+
"#{setting}/foo.txt", "#{setting}/bar.txt"
|
83
83
|
]
|
84
84
|
end
|
85
85
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
class HMACRequestPattern < WebMock::RequestPattern
|
2
|
+
def matches?(request_signature)
|
3
|
+
request_signature.headers['Authorization'].present? && super
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
module HMACHelpers
|
8
|
+
def stub_hmac_request(method, uri)
|
9
|
+
stub_request(method, uri).with { |request|
|
10
|
+
request.headers['Authorization'].present?
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def a_hmac_request(method, uri)
|
15
|
+
HMACRequestPattern.new method, uri
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
end
|
20
|
+
|
21
|
+
RSpec.configure do |config|
|
22
|
+
config.include HMACHelpers
|
23
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module MultipartHelpers
|
2
|
+
def a_multipart_request(method, uri)
|
3
|
+
MultipartRequestPattern.new method, uri
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class MultipartRequestPattern < WebMock::RequestPattern
|
8
|
+
def with_file(&block)
|
9
|
+
with { |request| block.call MultipartRequestToFile.call(request) }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class MultipartRequestToFile
|
14
|
+
def self.call(request)
|
15
|
+
new(request).call
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(request)
|
19
|
+
@request = request
|
20
|
+
end
|
21
|
+
|
22
|
+
def call
|
23
|
+
parsed["file"][:tempfile].read
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :request
|
29
|
+
|
30
|
+
def parsed
|
31
|
+
if Rack::Multipart.respond_to? :extract_multipart
|
32
|
+
Rack::Multipart.extract_multipart rack_request
|
33
|
+
else
|
34
|
+
Rack::Multipart.parse_multipart rack_env
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def rack_env
|
39
|
+
transformed_headers.merge 'rack.input' => StringIO.new(request.body)
|
40
|
+
end
|
41
|
+
|
42
|
+
def rack_request
|
43
|
+
Rack::Request.new rack_env
|
44
|
+
end
|
45
|
+
|
46
|
+
def transformed_headers
|
47
|
+
request.headers.keys.inject({}) do |hash, key|
|
48
|
+
hash[key.underscore.upcase] = request.headers[key]
|
49
|
+
hash
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
RSpec.configure do |config|
|
55
|
+
config.include MultipartHelpers
|
56
|
+
end
|