flying-sphinx 1.2.1 → 1.3.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.
- 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
|