riak-client 2.0.0.rc1 → 2.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cc9b9f7497052c55bb844b4d367c34845e57ec5a
4
- data.tar.gz: a40f43dc918e9f24a8cdfa52eee55eac6abe6cc7
3
+ metadata.gz: 6c5f3295a8250149c86f2b932a13f015621d42e5
4
+ data.tar.gz: 22dca3a33f295d67ada447302bcff4aed5bce2bf
5
5
  SHA512:
6
- metadata.gz: 3d38360e5a71d50a8038fd18117c1e1bd4b525869d8e6f1215b85aa9ba7c22e3069ff795cbfac2bac6156f348feb48cd7951e32e1a0718511e40aa0d809dfd89
7
- data.tar.gz: b0c5415b028c0d009cdca47c9c4ee620130ff60d4b320240a4a5593c343b232488c576f20b3602aff9b8dcf5256884de039d9dda8939ded6071b8d9a87c1dfea
6
+ metadata.gz: d4299561b7b0bd8ee05ee6e1f776e2ca9039d36e09761de4ae0e8dab16ad13633ef2392f2254232dbb9aad5225b0b5f81fc6d49518f63aa2285c1188147e9e37
7
+ data.tar.gz: 597699ef5a0f67ad7267d2cbce4524ca525639ebecc7475ed927b1f40b338d39857f1cf279362ff579cefe8ac09fbfdcd2643daddb3541c1b132ebda5e096185
data/Gemfile CHANGED
@@ -12,10 +12,6 @@ platforms :mri do
12
12
  gem 'yajl-ruby'
13
13
  end
14
14
 
15
- platforms :jruby do
16
- gem 'jruby-openssl'
17
- end
18
-
19
15
  platforms :jruby, :rbx do
20
16
  gem 'json'
21
17
  end
data/README.markdown CHANGED
@@ -1,4 +1,4 @@
1
- # Riak Ruby Client (riak-client) [![Build Status](https://secure.travis-ci.org/basho/riak-ruby-client.png)](http://travis-ci.org/basho/riak-ruby-client)
1
+ # Riak Ruby Client (riak-client)
2
2
 
3
3
  `riak-client` is a rich Ruby client/toolkit for Riak, Basho's
4
4
  distributed database that contains a basic wrapper around typical
@@ -10,6 +10,15 @@ and map-reduce.
10
10
  Ruby 1.9.3, 2.0, and 2.1 are supported. JRuby in 1.9 and 2.0 modes are
11
11
  also supported. `riak-client` is not compatible with Ruby 1.8.
12
12
 
13
+ In JRuby 1.7.13, OCSP validation is absent, and CRL validation always
14
+ fails. [This issue is being tracked][1] and this document will be updated when
15
+ it is fixed. Additionally, client certificate authentication doesn't work in
16
+ JRuby. [This issue is also being tracked][2], and this document will be updated
17
+ when it works.
18
+
19
+ [1]: https://github.com/jruby/jruby-openssl/issues/5
20
+ [2]: https://github.com/basho/riak_api/issues/65
21
+
13
22
  `riak-client` requires i18n, builder, beefcake, and multi_json. The
14
23
  cache store implementation requires ActiveSupport 3 or later.
15
24
 
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ end
15
15
 
16
16
  YARD::Rake::YardocTask.new :doc do |doc|
17
17
  doc.options = ["--markup markdown",
18
- "--markup-provider=redcarpet",
18
+ "--markup-provider=kramdown",
19
19
  "--charset utf-8",
20
20
  '-',
21
21
  'lib/**/*.rb',
@@ -1,5 +1,5 @@
1
1
  require 'openssl'
2
- require 'r509/cert/validator'
2
+ require 'cert_validator'
3
3
  require 'riak/client/beefcake/messages'
4
4
  require 'riak/errors/connection_error'
5
5
 
@@ -62,7 +62,11 @@ module Riak
62
62
 
63
63
  private
64
64
  def riak_cert
65
- @riak_cert ||= R509::Cert.new cert: @tls.peer_cert
65
+ @riak_cert ||= @tls.peer_cert
66
+ end
67
+
68
+ def ca_cert
69
+ @ca_cert ||= @tls.peer_cert_chain[1]
66
70
  end
67
71
 
68
72
  # Set up an SSL context with appropriate defaults for Riak TLS
@@ -70,8 +74,8 @@ module Riak
70
74
  @context = OpenSSL::SSL::SSLContext.new
71
75
 
72
76
  # Replace insecure defaults
73
- @context.ssl_version = @auth[:ssl_version] || :TLSv1_2_client
74
- @context.verify_mode = @auth[:verify_mode] || OpenSSL::SSL::VERIFY_PEER
77
+ @context.ssl_version = (@auth[:ssl_version] || default_ssl_version).to_sym
78
+ @context.verify_mode = (@auth[:verify_mode] || OpenSSL::SSL::VERIFY_PEER).to_i
75
79
 
76
80
  cert_ify
77
81
  key_ify
@@ -82,6 +86,18 @@ module Riak
82
86
  end
83
87
  end
84
88
 
89
+ # Choose the most secure SSL version available
90
+ def default_ssl_version
91
+ available = OpenSSL::SSL::SSLContext::METHODS
92
+ selected = %w{TLSv1_2_client TLSv1_1_client TLSv1.1 TLSv1_client TLS}.detect do |v|
93
+ available.include? v.to_sym
94
+ end
95
+
96
+ raise TlsError::SslVersionConfigurationError.new unless selected
97
+
98
+ return selected
99
+ end
100
+
85
101
  # Convert cert and client_ca fields to X509 Certs
86
102
  def cert_ify
87
103
  %w{ cert client_ca }.each do |k|
@@ -150,23 +166,24 @@ module Riak
150
166
  # Validate the TLS session
151
167
  def validate_session
152
168
  if @auth[:verify_hostname] &&
153
- !OpenSSL::SSL::verify_certificate_identity(riak_cert.cert, @host)
169
+ !OpenSSL::SSL::verify_certificate_identity(riak_cert, @host)
154
170
  raise TlsError::CertHostMismatchError.new
155
171
  end
156
172
 
157
- unless riak_cert.valid?
173
+ unless (riak_cert.not_before..riak_cert.not_after).cover? Time.now
158
174
  raise TlsError::CertNotValidError.new
159
175
  end
160
176
 
161
- validator = R509::Cert::Validator.new riak_cert
177
+ validator = CertValidator.new riak_cert, ca_cert
162
178
 
163
- validator_options = {}
164
- validator_options[:ocsp] = !!@auth[:ocsp]
165
- validator_options[:crl] = !!@auth[:crl]
166
- validator_options[:crl_file] = @auth[:crl_file]
179
+ validator.crl = try_load @auth[:crl_file] if @auth[:crl_file]
180
+
181
+ if @auth[:crl]
182
+ raise TlsError::CertRevokedError.new unless validator.crl_valid?
183
+ end
167
184
 
168
- unless validator.validate(validator_options)
169
- raise TlsError::CertRevokedError.new
185
+ if @auth[:ocsp]
186
+ raise TlsError::CertRevokedError.new unless validator.ocsp_valid?
170
187
  end
171
188
  end
172
189
 
@@ -25,7 +25,16 @@ module Riak
25
25
 
26
26
  def protocol
27
27
  p = Protocol.new socket
28
- yield p
28
+ in_request = false
29
+ result = nil
30
+ begin
31
+ in_request = true
32
+ result = yield p
33
+ in_request = false
34
+ ensure
35
+ reset_socket if in_request
36
+ end
37
+ return result
29
38
  end
30
39
 
31
40
  def new_socket
data/lib/riak/client.rb CHANGED
@@ -5,6 +5,7 @@ require 'riak'
5
5
  require 'riak/util/translation'
6
6
  require 'riak/util/escape'
7
7
  require 'riak/errors/failed_request'
8
+ require 'riak/errors/protobuffs_error'
8
9
  require 'riak/client/decaying'
9
10
  require 'riak/client/node'
10
11
  require 'riak/client/search'
@@ -43,6 +44,7 @@ module Riak
43
44
  Errno::ENETUNREACH,
44
45
  SocketError,
45
46
  SystemCallError,
47
+ Riak::ProtobuffsFailedHeader,
46
48
  ]
47
49
 
48
50
  Pool = ::Innertube::Pool
@@ -52,6 +52,30 @@ module Riak
52
52
  def context?
53
53
  !!@context
54
54
  end
55
+
56
+ def pretty_print(pp)
57
+ pp.object_group self do
58
+ pp.breakable
59
+ pp.text "bucket_type=#{@bucket_type}"
60
+ pp.comma_breakable
61
+ pp.text "bucket=#{@bucket.name}"
62
+ pp.comma_breakable
63
+ pp.text "key=#{@key}"
64
+
65
+ yield
66
+ end
67
+ end
68
+
69
+ def pretty_print_cycle(pp)
70
+ pp.object_group self do
71
+ pp.breakable
72
+ pp.text "#{@bucket_type}/#{@bucket.name}/#{@key}"
73
+ end
74
+ end
75
+
76
+ def inspect_name
77
+ "#<#{self.class.name} bucket=#{@bucket.name} key=#{@key} type=#{@bucket_type}>"
78
+ end
55
79
 
56
80
  private
57
81
  def client
@@ -54,6 +54,13 @@ module Riak
54
54
  def decrement(amount=1)
55
55
  increment -amount
56
56
  end
57
+
58
+ def pretty_print(pp)
59
+ super pp do
60
+ pp.comma_breakable
61
+ pp.text "value=#{value}"
62
+ end
63
+ end
57
64
 
58
65
  private
59
66
  def vivify(value)
@@ -55,6 +55,13 @@ module Riak
55
55
  increment batcher.accumulator
56
56
  end
57
57
 
58
+ def pretty_print(pp)
59
+ pp.object_group self do
60
+ pp.breakable
61
+ pp.pp value
62
+ end
63
+ end
64
+
58
65
  # @api private
59
66
  def self.update(increment)
60
67
  Operation::Update.new.tap do |op|
@@ -29,6 +29,28 @@ module Riak
29
29
  @parent.operate(name, wrapped_operation)
30
30
  end
31
31
 
32
+ def pretty_print(pp)
33
+ pp.object_group self do
34
+ %w{counters flags maps registers sets}.each do |h|
35
+ pp.comma_breakable
36
+ pp.text "#{h}="
37
+ pp.pp send h
38
+ end
39
+ end
40
+ end
41
+
42
+ def pretty_print_cycle(pp)
43
+ pp.text "InnerMap"
44
+ end
45
+
46
+ def to_value_h
47
+ %w{counters flags maps registers sets}.map do |k|
48
+ [k, send(k).to_value_h]
49
+ end.to_h
50
+ end
51
+
52
+ alias :value :to_value_h
53
+
32
54
  # @api private
33
55
  def self.delete
34
56
  Operation::Delete.new.tap do |op|
@@ -76,6 +76,13 @@ module Riak
76
76
  @parent.context?
77
77
  end
78
78
 
79
+ def pretty_print(pp)
80
+ pp.object_group self do
81
+ pp.breakable
82
+ pp.pp to_a
83
+ end
84
+ end
85
+
79
86
  # @api private
80
87
  def update(changes)
81
88
  Operation::Update.new.tap do |op|
data/lib/riak/crdt/map.rb CHANGED
@@ -32,7 +32,11 @@ module Riak
32
32
  def initialize(bucket, key, bucket_type=nil, options={})
33
33
  super(bucket, key, bucket_type || DEFAULT_BUCKET_TYPES[:map], options)
34
34
 
35
- initialize_collections
35
+ if key
36
+ initialize_collections
37
+ else
38
+ initialize_blank_collections
39
+ end
36
40
  end
37
41
 
38
42
  # Maps are frequently updated in batches. Use this method to get a
@@ -57,6 +61,24 @@ module Riak
57
61
  m.operate operation
58
62
  end
59
63
  end
64
+
65
+ def pretty_print(pp)
66
+ super pp do
67
+ %w{counters flags maps registers sets}.each do |h|
68
+ pp.comma_breakable
69
+ pp.text "#{h}="
70
+ pp.pp send h
71
+ end
72
+ end
73
+ end
74
+
75
+ def to_value_h
76
+ %w{counters flags maps registers sets}.map do |k|
77
+ [k, send(k).to_value_h]
78
+ end.to_h
79
+ end
80
+
81
+ alias :value :to_value_h
60
82
 
61
83
  private
62
84
  def vivify(data)
@@ -71,8 +93,12 @@ module Riak
71
93
  reload if dirty?
72
94
  end
73
95
 
96
+ def initialize_blank_collections
97
+ vivify counters: {}, flags: {}, maps: {}, registers: {}, sets: {}
98
+ end
99
+
74
100
  def write_operations(operations, *args)
75
- operator do |op|
101
+ result = operator do |op|
76
102
  op.operate(bucket.name,
77
103
  key,
78
104
  bucket_type,
@@ -80,6 +106,9 @@ module Riak
80
106
  *args
81
107
  )
82
108
  end
109
+
110
+ @key ||= result.key
111
+
83
112
  # collections break dirty tracking
84
113
  reload
85
114
  end
data/lib/riak/crdt/set.rb CHANGED
@@ -92,6 +92,13 @@ module Riak
92
92
 
93
93
  alias :delete :remove
94
94
 
95
+ def pretty_print(pp)
96
+ super pp do
97
+ pp.comma_breakable
98
+ pp.pp to_a
99
+ end
100
+ end
101
+
95
102
  private
96
103
  def vivify(value)
97
104
  @members = value
@@ -26,6 +26,45 @@ module Riak
26
26
  end
27
27
  end
28
28
 
29
+ def pretty_print(pp)
30
+ pp.object_group self do
31
+ pp.breakable
32
+ pp.text inspect_name
33
+ pp.comma_breakable
34
+ pp.text "parent="
35
+ @parent.pretty_print_cycle(pp)
36
+ pp.comma_breakable
37
+ pp.text "contents="
38
+ pp.pp @contents
39
+ end
40
+ # buf = []
41
+ # buf << inspect_name
42
+ # buf <<
43
+ # buf << "contents={#{inspect_contents}}"
44
+ # "#<#{self.class.name} #{buf.join ' '}>"
45
+ end
46
+
47
+ def pretty_print_cycle(pp)
48
+ pp.object_group self do
49
+ pp.breakable
50
+ @parent.pretty_print_cycle(pp)
51
+ end
52
+ end
53
+
54
+ def inspect_name
55
+ "contains=#{content_name}"
56
+ end
57
+
58
+ def pretty_print_contents(pp)
59
+ @contents.map do |k,v|
60
+ "#{k}=>#{v.inspect}"
61
+ end.join ', '
62
+ end
63
+
64
+ def content_name
65
+ @type.name
66
+ end
67
+
29
68
  # @api private
30
69
  def reparent(new_parent)
31
70
  reparented = self.class.new(@type,
@@ -114,6 +153,14 @@ module Riak
114
153
  !!@parent.context?
115
154
  end
116
155
 
156
+ def to_value_h
157
+ return @contents unless NEEDS_NAME.include? @type
158
+
159
+ @contents.map do |k, v|
160
+ [k, v.value]
161
+ end.to_h
162
+ end
163
+
117
164
  private
118
165
  def normalize_key(unnormalized_key)
119
166
  unnormalized_key.to_s
@@ -5,6 +5,12 @@ module Riak
5
5
  end
6
6
 
7
7
  class TlsError < ConnectionError
8
+ class SslVersionConfigurationError < TlsError
9
+ def initialize
10
+ super t('ssl.version_configuration_error')
11
+ end
12
+ end
13
+
8
14
  class CertHostMismatchError < TlsError
9
15
  def initialize
10
16
  super t('ssl.cert_host_mismatch')
@@ -59,6 +59,7 @@ en:
59
59
  pbc:
60
60
  failed_header: "Failed to receive a header from Riak."
61
61
  unexpected_eof: "Unexpected EOF on PBC socket"
62
+ unexpected_response: "Expected PBC %{expected}, got %{actual}."
62
63
  user_not_username: "Authentication hash expects :user, not :username."
63
64
  wanted_index_resp: "Expected IndexResp during secondary index query"
64
65
  wanted_dt_fetch_resp: "Expected PBC DtFetchResp during CRDT fetch"
@@ -80,6 +81,7 @@ en:
80
81
  read_data_error: "Tried to read cert or key from %{candidate}, caught error %{actual}."
81
82
  unexpected_during_init: "Expected %{expected}, got %{actual} with body %{body} during SSL/TLS initialization."
82
83
  unknown_key_type: "Can't figure out what the client key is. Expected it to be some kind of OpenSSL::PKey::PKey subclass, a filename string, or string data representing the key itself."
84
+ version_configuration_error: "Couldn't find a supported default ssl_version. Configure one that works with your version of Ruby."
83
85
  stale_write_prevented: "Stale write prevented by client."
84
86
  stored_function_invalid: "function must have :bucket and :key when a hash"
85
87
  streaming_bucket_list_without_block: "Streaming bucket list was requested but no block was given."
data/lib/riak/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Riak
2
- VERSION = "2.0.0.rc1"
2
+ VERSION = "2.0.0.rc2"
3
3
  end
data/riak-client.gemspec CHANGED
@@ -18,14 +18,14 @@ Gem::Specification.new do |gem|
18
18
  gem.add_development_dependency "rspec", "~> 3.0.0"
19
19
  gem.add_development_dependency 'rake', '~> 10.1.1'
20
20
  gem.add_development_dependency 'yard', '~> 0.8.7'
21
- gem.add_development_dependency 'redcarpet', '~> 3.0.0'
21
+ gem.add_development_dependency 'kramdown', '~> 1.4'
22
22
  gem.add_development_dependency 'simplecov', '~> 0.8.2'
23
23
 
24
24
  gem.add_runtime_dependency "i18n", ">=0.4.0"
25
25
  gem.add_runtime_dependency "beefcake", ">= 1.0.0.pre1"
26
26
  gem.add_runtime_dependency "multi_json", "~>1.0"
27
27
  gem.add_runtime_dependency "innertube", "~>1.0.2"
28
- gem.add_runtime_dependency 'r509-cert-validator', '~> 0.0.4'
28
+ gem.add_runtime_dependency 'cert_validator', '~> 0.0.1'
29
29
 
30
30
  # Files
31
31
 
@@ -20,12 +20,32 @@ describe "CRDTs", integration: true, test_client: true do
20
20
  end
21
21
  end
22
22
 
23
- describe 'an anonymous counter' do
24
- subject { Riak::Crdt::Counter.new bucket, nil }
25
- it 'accepts a Riak-assigned name' do
26
- subject.increment
27
- expect(subject.key).to be
28
- expect(subject.value).to eq 1
23
+ describe 'Riak-assigned names' do
24
+ describe 'an anonymous counter' do
25
+ subject { Riak::Crdt::Counter.new bucket, nil }
26
+ it 'accepts a Riak-assigned name' do
27
+ subject.increment
28
+ expect(subject.key).to be
29
+ expect(subject.value).to eq 1
30
+ end
31
+ end
32
+
33
+ describe 'an anonymous set' do
34
+ subject { Riak::Crdt::Set.new bucket, nil }
35
+ it 'accepts a Riak-assigned name' do
36
+ subject.add 'sandwich'
37
+ expect(subject.key).to be
38
+ expect(subject).to include 'sandwich'
39
+ end
40
+ end
41
+
42
+ describe 'an anonymous map' do
43
+ subject { Riak::Crdt::Map.new bucket, nil }
44
+ it 'accepts a Riak-assigned name' do
45
+ subject.registers['coat_pattern'] = 'tabby'
46
+ expect(subject.key).to be
47
+ expect(subject.registers['coat_pattern']).to eq 'tabby'
48
+ end
29
49
  end
30
50
  end
31
51
 
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+ require 'timeout'
3
+
4
+ describe 'Protocol Buffers', test_client: true do
5
+ describe 'interrupted requests' do
6
+
7
+ let(:bucket){ random_bucket 'interrupted_requests' }
8
+
9
+ before do
10
+ first = bucket.new 'first'
11
+ first.data = 'first'
12
+ first.content_type = 'text/plain'
13
+ first.store
14
+
15
+ second = bucket.new 'second'
16
+ second.data = 'second'
17
+ second.content_type = 'text/plain'
18
+ second.store
19
+ end
20
+
21
+ it 'fails out when a request is interrupted, and never returns the wrong payload' do
22
+ expect do
23
+ Timeout.timeout 1 do
24
+ loop do
25
+ expect(bucket.get('first').data).to eq 'first'
26
+ end
27
+ end
28
+ end.to raise_error Timeout::Error
29
+
30
+ expect(bucket.get('second').data).to eq 'second'
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Secondary indexes', test_client: true, integration: true do
4
+ let(:bucket){ random_bucket '2i-integration' }
5
+ before do
6
+ 50.times do |i|
7
+ bucket.new(i.to_s).tap do |obj|
8
+ obj.indexes["index_int"] << i
9
+ obj.indexes["index_bin"] << i.to_s
10
+ obj.data = [i]
11
+ obj.store
12
+ end
13
+ end
14
+ end
15
+
16
+ it "finds keys for an equality query" do
17
+ expect(bucket.get_index('index_int', 20)).to eq(["20"])
18
+ end
19
+
20
+ it "finds keys for a range query" do
21
+ expect(bucket.get_index('index_int', 19..21)).to match_array(["19","20", "21"])
22
+ end
23
+
24
+ it "returns an empty array for a query that does not match any keys" do
25
+ expect(bucket.get_index('index_int', 10000)).to eq([])
26
+ end
27
+
28
+ it "returns terms" do
29
+ results = nil
30
+ expect do
31
+ results = bucket.get_index('index_int',
32
+ 19..21,
33
+ return_terms: true)
34
+ end.to_not raise_error
35
+
36
+ expect(results).to be_a Array
37
+ expect(results.with_terms).to be_a Hash
38
+ end
39
+
40
+ it "returns terms matching a term_regex" do
41
+ results = nil
42
+ expect do
43
+ results = bucket.get_index('index_bin',
44
+ '19'..'21',
45
+ return_terms: true,
46
+ term_regex: '20')
47
+ end.to_not raise_error
48
+
49
+ terms = results.with_terms
50
+
51
+ expect(terms['20']).to be
52
+ expect(terms['19']).to be_empty
53
+ end
54
+ end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'riak'
3
3
  require 'riak/errors/connection_error'
4
- require 'r509/cert/validator/errors'
4
+ require 'cert_validator/errors'
5
5
 
6
6
  describe 'Secure Protobuffs', test_client: true, integration: true do
7
7
  let(:config){ test_client_configuration.dup }
@@ -59,9 +59,15 @@ describe 'Secure Protobuffs', test_client: true, integration: true do
59
59
  it "refuses to connect if the server cert is revoked" do
60
60
  revoked_auth_config = config.dup
61
61
  revoked_auth_config[:authentication] = revoked_auth_config[:authentication].dup
62
-
62
+
63
63
  revoked_auth_config[:authentication][:crl_file] =
64
- File.expand_path(File.join(__dir__, '..', '..', 'support', 'certs', 'server.crl'))
64
+ File.expand_path(File.join('..',
65
+ '..',
66
+ '..',
67
+ 'support',
68
+ 'certs',
69
+ 'server.crl'),
70
+ __FILE__)
65
71
  revoked_auth_config[:authentication][:crl] = true
66
72
 
67
73
  revoked_auth_client = Riak::Client.new revoked_auth_config
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'riak/errors/protobuffs_error'
2
3
 
3
4
  describe Riak::Client, test_client: true do
4
5
  describe "when initializing" do
@@ -27,6 +28,16 @@ describe Riak::Client, test_client: true do
27
28
  it "should create a client ID if not specified" do
28
29
  expect(Riak::Client.new(pb_port: test_client.nodes.first.pb_port).client_id).not_to be_nil
29
30
  end
31
+
32
+ it "should accept multiple nodes" do
33
+ client = Riak::Client.new :nodes => [
34
+ {:host => 'riak1.basho.com'},
35
+ {:host => 'riak2.basho.com', :pb_port => 1234},
36
+ {:host => 'riak3.basho.com', :pb_port => 5678}
37
+ ]
38
+ expect(client.nodes.size).to eq(3)
39
+ expect(client.nodes.first.host).to eq("riak1.basho.com")
40
+ end
30
41
  end
31
42
 
32
43
  it "should expose a Stamp object" do
@@ -173,4 +184,38 @@ describe Riak::Client, test_client: true do
173
184
  expect(buckets.size).to eq(2)
174
185
  end
175
186
  end
187
+
188
+ describe "when receiving errors from the backend"
189
+ before do
190
+ @client = Riak::Client.new
191
+ end
192
+
193
+ it "should retry on recoverable errors" do
194
+ call_count = 0
195
+
196
+ begin
197
+ @client.backend do |b|
198
+ call_count += 1
199
+ raise Riak::ProtobuffsFailedHeader
200
+ end
201
+ rescue RuntimeError
202
+ end
203
+
204
+ expect(call_count).to eq(3)
205
+ end
206
+
207
+ it "should throw a RuntimeError if it runs out of retries" do
208
+ error = nil
209
+ begin
210
+ @client.backend do |b|
211
+ raise Riak::ProtobuffsFailedHeader
212
+ end
213
+ rescue RuntimeError => e
214
+ error = e
215
+ end
216
+
217
+ expect(error).not_to be_nil
218
+ expect(error).to be_instance_of(RuntimeError)
219
+ end
220
+
176
221
  end
@@ -1,7 +1,10 @@
1
- # protip: don't run more than one node, tests are sensitive to quorums
2
- nodes:
3
- - {host: 'localhost', pb_port: 17017}
4
- # authentication:
5
- # user: 'user'
6
- # password: 'password'
7
- # ca_file: /Users/bkerley/Documents/riak-ruby-client/spec/support/certs/ca.crt
1
+ # This file is used for configuring test_client used by
2
+ # many of the integration tests.
3
+ #
4
+ # Simply set the arguments you'd normally pass to
5
+ # Riak::Client.new in the file.
6
+ #
7
+ # Don't run multiple nodes, integration tests include
8
+ # quorum checks that may result in race conditions.
9
+
10
+ pb_port: 17017
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riak-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.rc1
4
+ version: 2.0.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Cribbs
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-06-23 00:00:00.000000000 Z
12
+ date: 2014-09-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -54,19 +54,19 @@ dependencies:
54
54
  - !ruby/object:Gem::Version
55
55
  version: 0.8.7
56
56
  - !ruby/object:Gem::Dependency
57
- name: redcarpet
57
+ name: kramdown
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
60
  - - "~>"
61
61
  - !ruby/object:Gem::Version
62
- version: 3.0.0
62
+ version: '1.4'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - "~>"
68
68
  - !ruby/object:Gem::Version
69
- version: 3.0.0
69
+ version: '1.4'
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: simplecov
72
72
  requirement: !ruby/object:Gem::Requirement
@@ -138,19 +138,19 @@ dependencies:
138
138
  - !ruby/object:Gem::Version
139
139
  version: 1.0.2
140
140
  - !ruby/object:Gem::Dependency
141
- name: r509-cert-validator
141
+ name: cert_validator
142
142
  requirement: !ruby/object:Gem::Requirement
143
143
  requirements:
144
144
  - - "~>"
145
145
  - !ruby/object:Gem::Version
146
- version: 0.0.4
146
+ version: 0.0.1
147
147
  type: :runtime
148
148
  prerelease: false
149
149
  version_requirements: !ruby/object:Gem::Requirement
150
150
  requirements:
151
151
  - - "~>"
152
152
  - !ruby/object:Gem::Version
153
- version: 0.0.4
153
+ version: 0.0.1
154
154
  description: riak-client is a rich client for Riak, the distributed database by Basho.
155
155
  It supports the full HTTP and Protocol Buffers interfaces including storage operations,
156
156
  bucket configuration, link-walking, secondary indexes and map-reduce.
@@ -262,7 +262,9 @@ files:
262
262
  - spec/integration/riak/crdt_spec.rb
263
263
  - spec/integration/riak/crdt_validation/map_spec.rb
264
264
  - spec/integration/riak/crdt_validation/set_spec.rb
265
+ - spec/integration/riak/protobuffs/interrupted_request_spec.rb
265
266
  - spec/integration/riak/protobuffs_backends_spec.rb
267
+ - spec/integration/riak/secondary_index_spec.rb
266
268
  - spec/integration/riak/security_spec.rb
267
269
  - spec/integration/riak/threading_spec.rb
268
270
  - spec/integration/yokozuna/index_spec.rb
@@ -271,7 +273,6 @@ files:
271
273
  - spec/riak/beefcake_protobuffs_backend/crdt_operator_spec.rb
272
274
  - spec/riak/beefcake_protobuffs_backend/object_methods_spec.rb
273
275
  - spec/riak/beefcake_protobuffs_backend/protocol_spec.rb
274
- - spec/riak/beefcake_protobuffs_backend/socket_spec.rb
275
276
  - spec/riak/beefcake_protobuffs_backend_spec.rb
276
277
  - spec/riak/bucket_spec.rb
277
278
  - spec/riak/client_spec.rb
@@ -340,7 +341,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
340
341
  version: 1.3.1
341
342
  requirements: []
342
343
  rubyforge_project:
343
- rubygems_version: 2.3.0
344
+ rubygems_version: 2.2.0
344
345
  signing_key:
345
346
  specification_version: 4
346
347
  summary: riak-client is a rich client for Riak, the distributed database by Basho.
@@ -362,7 +363,9 @@ test_files:
362
363
  - spec/integration/riak/crdt_spec.rb
363
364
  - spec/integration/riak/crdt_validation/map_spec.rb
364
365
  - spec/integration/riak/crdt_validation/set_spec.rb
366
+ - spec/integration/riak/protobuffs/interrupted_request_spec.rb
365
367
  - spec/integration/riak/protobuffs_backends_spec.rb
368
+ - spec/integration/riak/secondary_index_spec.rb
366
369
  - spec/integration/riak/security_spec.rb
367
370
  - spec/integration/riak/threading_spec.rb
368
371
  - spec/integration/yokozuna/index_spec.rb
@@ -371,7 +374,6 @@ test_files:
371
374
  - spec/riak/beefcake_protobuffs_backend/crdt_operator_spec.rb
372
375
  - spec/riak/beefcake_protobuffs_backend/object_methods_spec.rb
373
376
  - spec/riak/beefcake_protobuffs_backend/protocol_spec.rb
374
- - spec/riak/beefcake_protobuffs_backend/socket_spec.rb
375
377
  - spec/riak/beefcake_protobuffs_backend_spec.rb
376
378
  - spec/riak/bucket_spec.rb
377
379
  - spec/riak/client_spec.rb
@@ -1,151 +0,0 @@
1
- require 'spec_helper'
2
- require 'riak/client/beefcake/socket'
3
-
4
- describe Riak::Client::BeefcakeProtobuffsBackend::BeefcakeSocket do
5
- let(:host){ 'host' }
6
- let(:pb_port){ 8087 }
7
- let(:tcp_socket_instance){ double 'TCPSocket' }
8
-
9
- let(:ssl){ OpenSSL::SSL }
10
-
11
- describe 'without authentication configured' do
12
- let(:options){ Hash.new }
13
- it 'should start a tcp connection and not start a tls connection' do
14
- expect(TCPSocket).to receive(:new).
15
- with(host, pb_port).
16
- and_return(tcp_socket_instance)
17
-
18
- expect(tcp_socket_instance).to receive(:setsockopt).
19
- with(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true)
20
-
21
- expect(ssl::SSLSocket).not_to receive(:new)
22
-
23
- described_class.new host, pb_port
24
- end
25
- end
26
-
27
- describe 'with authentication configured' do
28
- let(:user){ 'user' }
29
- let(:password){ 'password' }
30
- let(:options) do
31
- {
32
- authentication: {
33
- user: user,
34
- password: password
35
- }
36
- }
37
- end
38
- let(:ssl_socket_instance){ double 'SSLSocket' }
39
- let(:ssl_peer_cert){ double 'Peer Certificate' }
40
- let(:r509_cert){ double 'R509::Cert' }
41
- let(:rcv_instance){ double 'R509::Cert::Validator instance' }
42
-
43
- it 'should start a tcp and a tls connection, and send authentication info' do
44
- expect(TCPSocket).to receive(:new).
45
- with(host, pb_port).
46
- and_return(tcp_socket_instance)
47
-
48
- expect(tcp_socket_instance).to receive(:setsockopt).
49
- with(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true)
50
-
51
- allow(tcp_socket_instance).to receive(:write)
52
-
53
- # StartTls
54
- expect(tcp_socket_instance).to receive(:read).
55
- with(5).
56
- and_return([1, 255].pack 'NC')
57
-
58
- expect(ssl::SSLSocket).to receive(:new).
59
- with(tcp_socket_instance, kind_of(OpenSSL::SSL::SSLContext)).
60
- and_return(ssl_socket_instance)
61
-
62
- expect(ssl_socket_instance).to receive(:connect)
63
-
64
- allow(ssl_socket_instance).to receive(:write)
65
-
66
- expect(ssl_socket_instance).to receive(:peer_cert).
67
- and_return(ssl_peer_cert)
68
- expect(R509::Cert).to receive(:new).
69
- with(cert: ssl_peer_cert).
70
- and_return(r509_cert)
71
- allow(r509_cert).to receive(:valid?).and_return(true)
72
- expect(R509::Cert::Validator).to receive(:new).
73
- with(r509_cert).
74
- and_return(rcv_instance)
75
-
76
- expect(rcv_instance).to receive(:validate).
77
- with(ocsp: false, crl: false, crl_file: nil).
78
- and_return(true)
79
-
80
- # AuthResp
81
- expect(ssl_socket_instance).to receive(:read).
82
- with(5).
83
- and_return([1, 254].pack 'NC')
84
-
85
- # PingResp
86
- expect(ssl_socket_instance).to receive(:read).
87
- with(5).
88
- and_return([1, 2].pack 'NC')
89
-
90
- described_class.new host, pb_port, options
91
- end
92
-
93
- it 'should pass pass TLS options through to OpenSSL' do
94
- options[:authentication][:ca_file] = 'spec/support/certs/ca.crt'
95
- options[:authentication][:key] = 'spec/support/certs/client.key'
96
-
97
- expect(TCPSocket).to receive(:new).
98
- with(host, pb_port).
99
- and_return(tcp_socket_instance)
100
-
101
- expect(tcp_socket_instance).to receive(:setsockopt).
102
- with(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true)
103
-
104
- allow(tcp_socket_instance).to receive(:write)
105
-
106
- # StartTls
107
- expect(tcp_socket_instance).to receive(:read).
108
- with(5).
109
- and_return([1, 255].pack 'NC')
110
-
111
- expect(ssl::SSLSocket).to receive(:new) do |sock, ctx|
112
- expect(sock).to eq tcp_socket_instance
113
- expect(ctx).to be_a OpenSSL::SSL::SSLContext
114
- expect(ctx.key).to be_a OpenSSL::PKey::PKey
115
- expect(ctx.ca_file).to eq 'spec/support/certs/ca.crt'
116
-
117
- ssl_socket_instance
118
- end
119
-
120
- expect(ssl_socket_instance).to receive(:connect)
121
-
122
- allow(ssl_socket_instance).to receive(:write)
123
-
124
- expect(ssl_socket_instance).to receive(:peer_cert).
125
- and_return(ssl_peer_cert)
126
- expect(R509::Cert).to receive(:new).
127
- with(cert: ssl_peer_cert).
128
- and_return(r509_cert)
129
- allow(r509_cert).to receive(:valid?).and_return(true)
130
- expect(R509::Cert::Validator).to receive(:new).
131
- with(r509_cert).
132
- and_return(rcv_instance)
133
-
134
- expect(rcv_instance).to receive(:validate).
135
- with(ocsp: false, crl: false, crl_file: nil).
136
- and_return(true)
137
-
138
- # AuthResp
139
- expect(ssl_socket_instance).to receive(:read).
140
- with(5).
141
- and_return([1, 254].pack 'NC')
142
-
143
- # PingResp
144
- expect(ssl_socket_instance).to receive(:read).
145
- with(5).
146
- and_return([1, 2].pack 'NC')
147
-
148
- described_class.new host, pb_port, options
149
- end
150
- end
151
- end