riak-client 2.0.0.rc1 → 2.0.0.rc2

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 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