couchbase 4.2.5 → 4.2.6-dev
Sign up to get free protection for your applications and to get access to all the features.
- package/deps/couchbase-cxx-client/CMakeLists.txt +9 -1
- package/deps/couchbase-cxx-client/bin/api.rb +234 -0
- package/deps/couchbase-cxx-client/bin/create-search-index +18 -135
- package/deps/couchbase-cxx-client/bin/init-cluster +17 -139
- package/deps/couchbase-cxx-client/bin/load-sample-buckets +54 -0
- package/deps/couchbase-cxx-client/core/cluster.hxx +33 -12
- package/deps/couchbase-cxx-client/core/cluster_options.hxx +3 -0
- package/deps/couchbase-cxx-client/core/crud_component.cxx +51 -22
- package/deps/couchbase-cxx-client/core/impl/build_deferred_query_indexes.cxx +115 -50
- package/deps/couchbase-cxx-client/core/impl/cluster.cxx +6 -0
- package/deps/couchbase-cxx-client/core/impl/create_bucket.cxx +155 -0
- package/deps/couchbase-cxx-client/core/impl/create_query_index.cxx +172 -59
- package/deps/couchbase-cxx-client/core/impl/dns_srv_tracker.cxx +2 -1
- package/deps/couchbase-cxx-client/core/impl/drop_bucket.cxx +66 -0
- package/deps/couchbase-cxx-client/core/impl/drop_query_index.cxx +138 -59
- package/deps/couchbase-cxx-client/core/impl/flush_bucket.cxx +66 -0
- package/deps/couchbase-cxx-client/core/impl/get_all_buckets.cxx +163 -0
- package/deps/couchbase-cxx-client/core/impl/get_all_query_indexes.cxx +67 -37
- package/deps/couchbase-cxx-client/core/impl/get_bucket.cxx +153 -0
- package/deps/couchbase-cxx-client/core/impl/internal_manager_error_context.cxx +113 -0
- package/deps/couchbase-cxx-client/core/impl/internal_manager_error_context.hxx +60 -0
- package/deps/couchbase-cxx-client/core/impl/key_value_error_category.cxx +2 -4
- package/deps/couchbase-cxx-client/core/impl/manager_error_context.cxx +100 -0
- package/deps/couchbase-cxx-client/core/impl/query.cxx +1 -0
- package/deps/couchbase-cxx-client/core/impl/update_bucket.cxx +130 -0
- package/deps/couchbase-cxx-client/core/impl/watch_query_indexes.cxx +53 -29
- package/deps/couchbase-cxx-client/core/io/dns_client.cxx +71 -38
- package/deps/couchbase-cxx-client/core/io/dns_config.cxx +5 -4
- package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +5 -6
- package/deps/couchbase-cxx-client/core/meta/features.hxx +6 -0
- package/deps/couchbase-cxx-client/core/operations/document_query.cxx +11 -0
- package/deps/couchbase-cxx-client/core/operations/document_query.hxx +1 -0
- package/deps/couchbase-cxx-client/core/origin.cxx +270 -0
- package/deps/couchbase-cxx-client/core/origin.hxx +2 -0
- package/deps/couchbase-cxx-client/core/protocol/status.cxx +2 -2
- package/deps/couchbase-cxx-client/core/range_scan_options.cxx +3 -27
- package/deps/couchbase-cxx-client/core/range_scan_options.hxx +13 -17
- package/deps/couchbase-cxx-client/core/range_scan_orchestrator.cxx +367 -170
- package/deps/couchbase-cxx-client/core/range_scan_orchestrator.hxx +13 -2
- package/deps/couchbase-cxx-client/core/range_scan_orchestrator_options.hxx +5 -3
- package/deps/couchbase-cxx-client/core/scan_options.hxx +0 -19
- package/deps/couchbase-cxx-client/core/scan_result.cxx +19 -5
- package/deps/couchbase-cxx-client/core/scan_result.hxx +5 -2
- package/deps/couchbase-cxx-client/core/timeout_defaults.hxx +2 -3
- package/deps/couchbase-cxx-client/core/topology/capabilities.hxx +1 -0
- package/deps/couchbase-cxx-client/core/topology/capabilities_fmt.hxx +2 -0
- package/deps/couchbase-cxx-client/core/topology/collections_manifest_fmt.hxx +1 -1
- package/deps/couchbase-cxx-client/core/topology/configuration.hxx +5 -0
- package/deps/couchbase-cxx-client/core/topology/configuration_json.hxx +2 -0
- package/deps/couchbase-cxx-client/core/utils/connection_string.cxx +4 -0
- package/deps/couchbase-cxx-client/couchbase/behavior_options.hxx +19 -2
- package/deps/couchbase-cxx-client/couchbase/bucket_manager.hxx +135 -0
- package/deps/couchbase-cxx-client/couchbase/build_query_index_options.hxx +0 -30
- package/deps/couchbase-cxx-client/couchbase/cluster.hxx +14 -0
- package/deps/couchbase-cxx-client/couchbase/collection_query_index_manager.hxx +7 -48
- package/deps/couchbase-cxx-client/couchbase/create_bucket_options.hxx +41 -0
- package/deps/couchbase-cxx-client/couchbase/create_primary_query_index_options.hxx +0 -29
- package/deps/couchbase-cxx-client/couchbase/create_query_index_options.hxx +0 -33
- package/deps/couchbase-cxx-client/couchbase/drop_bucket_options.hxx +41 -0
- package/deps/couchbase-cxx-client/couchbase/drop_primary_query_index_options.hxx +0 -30
- package/deps/couchbase-cxx-client/couchbase/drop_query_index_options.hxx +0 -31
- package/deps/couchbase-cxx-client/couchbase/error_codes.hxx +1 -2
- package/deps/couchbase-cxx-client/couchbase/flush_bucket_options.hxx +41 -0
- package/deps/couchbase-cxx-client/couchbase/get_all_buckets_options.hxx +44 -0
- package/deps/couchbase-cxx-client/couchbase/get_all_query_indexes_options.hxx +0 -30
- package/deps/couchbase-cxx-client/couchbase/get_bucket_options.hxx +43 -0
- package/deps/couchbase-cxx-client/couchbase/management/bucket_settings.hxx +116 -0
- package/deps/couchbase-cxx-client/couchbase/manager_error_context.hxx +29 -53
- package/deps/couchbase-cxx-client/couchbase/query_index_manager.hxx +16 -83
- package/deps/couchbase-cxx-client/couchbase/query_options.hxx +18 -0
- package/deps/couchbase-cxx-client/couchbase/security_options.hxx +15 -0
- package/deps/couchbase-cxx-client/couchbase/update_bucket_options.hxx +41 -0
- package/deps/couchbase-cxx-client/couchbase/watch_query_indexes_options.hxx +0 -31
- package/deps/couchbase-cxx-client/docs/cbc-analytics.md +1 -0
- package/deps/couchbase-cxx-client/docs/cbc-get.md +1 -0
- package/deps/couchbase-cxx-client/docs/cbc-pillowfight.md +1 -0
- package/deps/couchbase-cxx-client/docs/cbc-query.md +1 -0
- package/deps/couchbase-cxx-client/docs/cbc.md +10 -0
- package/deps/couchbase-cxx-client/test/CMakeLists.txt +1 -0
- package/deps/couchbase-cxx-client/test/test_integration_collections.cxx +6 -0
- package/deps/couchbase-cxx-client/test/test_integration_crud.cxx +5 -0
- package/deps/couchbase-cxx-client/test/test_integration_examples.cxx +137 -1
- package/deps/couchbase-cxx-client/test/test_integration_management.cxx +709 -266
- package/deps/couchbase-cxx-client/test/test_integration_query.cxx +19 -7
- package/deps/couchbase-cxx-client/test/test_integration_range_scan.cxx +351 -112
- package/deps/couchbase-cxx-client/test/test_integration_search.cxx +10 -1
- package/deps/couchbase-cxx-client/test/test_transaction_public_async_api.cxx +13 -12
- package/deps/couchbase-cxx-client/test/test_transaction_public_blocking_api.cxx +27 -21
- package/deps/couchbase-cxx-client/test/test_unit_query.cxx +75 -0
- package/deps/couchbase-cxx-client/test/utils/server_version.hxx +5 -0
- package/deps/couchbase-cxx-client/test/utils/wait_until.cxx +29 -10
- package/deps/couchbase-cxx-client/test/utils/wait_until.hxx +3 -1
- package/deps/couchbase-cxx-client/tools/utils.cxx +4 -1
- package/dist/binding.d.ts +21 -16
- package/dist/binding.js +1 -4
- package/dist/bindingutilities.d.ts +6 -1
- package/dist/bindingutilities.js +36 -1
- package/dist/collection.d.ts +65 -3
- package/dist/collection.js +107 -0
- package/dist/crudoptypes.d.ts +34 -0
- package/dist/crudoptypes.js +18 -1
- package/dist/queryexecutor.js +1 -0
- package/dist/querytypes.d.ts +7 -0
- package/dist/rangeScan.d.ts +107 -0
- package/dist/rangeScan.js +91 -0
- package/dist/streamablepromises.d.ts +6 -0
- package/dist/streamablepromises.js +25 -1
- package/package.json +12 -13
- package/src/addondata.hpp +1 -0
- package/src/binding.cpp +5 -2
- package/src/connection.cpp +108 -2
- package/src/connection.hpp +1 -0
- package/src/constants.cpp +2 -12
- package/src/jstocbpp_autogen.hpp +49 -22
- package/src/jstocbpp_basic.hpp +2 -8
- package/src/mutationtoken.cpp +13 -0
- package/src/scan_iterator.cpp +90 -0
- package/src/scan_iterator.hpp +30 -0
- package/tools/gen-bindings-json.py +9 -8
- package/deps/couchbase-cxx-client/core/impl/collection_query_index_manager.cxx +0 -93
@@ -100,6 +100,7 @@ set(couchbase_cxx_client_FILES
|
|
100
100
|
core/free_form_http_request.cxx
|
101
101
|
core/key_value_config.cxx
|
102
102
|
core/n1ql_query_options.cxx
|
103
|
+
core/origin.cxx
|
103
104
|
core/range_scan_options.cxx
|
104
105
|
core/range_scan_orchestrator.cxx
|
105
106
|
core/retry_orchestrator.cxx
|
@@ -265,10 +266,10 @@ set(couchbase_cxx_client_FILES
|
|
265
266
|
core/impl/boolean_query.cxx
|
266
267
|
core/impl/build_deferred_query_indexes.cxx
|
267
268
|
core/impl/cluster.cxx
|
268
|
-
core/impl/collection_query_index_manager.cxx
|
269
269
|
core/impl/common_error_category.cxx
|
270
270
|
core/impl/configuration_profiles_registry.cxx
|
271
271
|
core/impl/conjunction_query.cxx
|
272
|
+
core/impl/create_bucket.cxx
|
272
273
|
core/impl/create_query_index.cxx
|
273
274
|
core/impl/date_range.cxx
|
274
275
|
core/impl/date_range_facet.cxx
|
@@ -277,24 +278,29 @@ set(couchbase_cxx_client_FILES
|
|
277
278
|
core/impl/decrement.cxx
|
278
279
|
core/impl/disjunction_query.cxx
|
279
280
|
core/impl/dns_srv_tracker.cxx
|
281
|
+
core/impl/drop_bucket.cxx
|
280
282
|
core/impl/drop_query_index.cxx
|
281
283
|
core/impl/exists.cxx
|
282
284
|
core/impl/expiry.cxx
|
283
285
|
core/impl/fail_fast_retry_strategy.cxx
|
284
286
|
core/impl/field_level_encryption_error_category.cxx
|
287
|
+
core/impl/flush_bucket.cxx
|
285
288
|
core/impl/geo_bounding_box_query.cxx
|
286
289
|
core/impl/geo_distance_query.cxx
|
287
290
|
core/impl/geo_polygon_query.cxx
|
288
291
|
core/impl/get.cxx
|
292
|
+
core/impl/get_all_buckets.cxx
|
289
293
|
core/impl/get_all_query_indexes.cxx
|
290
294
|
core/impl/get_all_replicas.cxx
|
291
295
|
core/impl/get_and_lock.cxx
|
292
296
|
core/impl/get_and_touch.cxx
|
293
297
|
core/impl/get_any_replica.cxx
|
298
|
+
core/impl/get_bucket.cxx
|
294
299
|
core/impl/get_replica.cxx
|
295
300
|
core/impl/increment.cxx
|
296
301
|
core/impl/insert.cxx
|
297
302
|
core/impl/internal_date_range_facet_result.cxx
|
303
|
+
core/impl/internal_manager_error_context.cxx
|
298
304
|
core/impl/internal_numeric_range_facet_result.cxx
|
299
305
|
core/impl/internal_search_error_context.cxx
|
300
306
|
core/impl/internal_search_meta_data.cxx
|
@@ -306,6 +312,7 @@ set(couchbase_cxx_client_FILES
|
|
306
312
|
core/impl/key_value_error_context.cxx
|
307
313
|
core/impl/lookup_in.cxx
|
308
314
|
core/impl/management_error_category.cxx
|
315
|
+
core/impl/manager_error_context.cxx
|
309
316
|
core/impl/match_all_query.cxx
|
310
317
|
core/impl/match_none_query.cxx
|
311
318
|
core/impl/match_phrase_query.cxx
|
@@ -368,6 +375,7 @@ set(couchbase_cxx_client_FILES
|
|
368
375
|
core/impl/transaction_get_result.cxx
|
369
376
|
core/impl/transaction_op_error_category.cxx
|
370
377
|
core/impl/unlock.cxx
|
378
|
+
core/impl/update_bucket.cxx
|
371
379
|
core/impl/upsert.cxx
|
372
380
|
core/impl/view_error_category.cxx
|
373
381
|
core/impl/watch_query_indexes.cxx
|
@@ -0,0 +1,234 @@
|
|
1
|
+
# Copyright 2020-2021 Couchbase, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require "openssl"
|
16
|
+
require "net/http"
|
17
|
+
require "json"
|
18
|
+
|
19
|
+
class Object
|
20
|
+
def to_b
|
21
|
+
![nil, false, 0, "", "0", "f", "F", "false", "FALSE", "off", "OFF", "no", "NO"].include?(self)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
class API
|
27
|
+
def initialize(options)
|
28
|
+
@options = options
|
29
|
+
connect
|
30
|
+
end
|
31
|
+
|
32
|
+
def connect
|
33
|
+
puts "# CONNECT #{@options}"
|
34
|
+
@client = Net::HTTP.start(@options[:host], @options[:port],
|
35
|
+
use_ssl: @options[:strict_encryption],
|
36
|
+
verify_mode: OpenSSL::SSL::VERIFY_NONE)
|
37
|
+
end
|
38
|
+
|
39
|
+
def url(path)
|
40
|
+
"#{@client.use_ssl? ? 'https' : 'http'}://#{@options[:username]}@#{@options[:host]}:#{@options[:port]}#{path}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def decode_response(response)
|
44
|
+
payload =
|
45
|
+
if response['content-type'] =~ /application\/json/
|
46
|
+
JSON.parse(response.body)
|
47
|
+
else
|
48
|
+
response.body
|
49
|
+
end
|
50
|
+
if @options[:verbose]
|
51
|
+
p status: response.code, payload: payload
|
52
|
+
end
|
53
|
+
payload
|
54
|
+
end
|
55
|
+
|
56
|
+
def setup_request(request)
|
57
|
+
request.basic_auth(@options[:username], @options[:password])
|
58
|
+
request['accept'] = "application/json"
|
59
|
+
end
|
60
|
+
|
61
|
+
def get(path)
|
62
|
+
puts "# GET #{url(path)}"
|
63
|
+
req = Net::HTTP::Get.new(path)
|
64
|
+
setup_request(req)
|
65
|
+
res = @client.request(req)
|
66
|
+
decode_response(res)
|
67
|
+
rescue EOFError
|
68
|
+
connect
|
69
|
+
retry
|
70
|
+
rescue => ex
|
71
|
+
puts "#{__method__}: #{ex}, sleep for 1 second and retry"
|
72
|
+
sleep(1)
|
73
|
+
retry
|
74
|
+
end
|
75
|
+
|
76
|
+
def post_form(path, fields = {})
|
77
|
+
puts "# POST #{url(path)} #{fields}"
|
78
|
+
req = Net::HTTP::Post.new(path)
|
79
|
+
setup_request(req)
|
80
|
+
req.form_data = fields
|
81
|
+
res = @client.request(req)
|
82
|
+
decode_response(res)
|
83
|
+
rescue EOFError
|
84
|
+
connect
|
85
|
+
retry
|
86
|
+
rescue => ex
|
87
|
+
puts "#{__method__}: #{ex}, sleep for 1 second and retry"
|
88
|
+
sleep(1)
|
89
|
+
retry
|
90
|
+
end
|
91
|
+
|
92
|
+
def post_json(path, object)
|
93
|
+
data = JSON.generate(object)
|
94
|
+
puts "# POST #{url(path)} #{data}"
|
95
|
+
req = Net::HTTP::Post.new(path)
|
96
|
+
req['content-type'] = "application/json"
|
97
|
+
setup_request(req)
|
98
|
+
res = @client.request(req, data)
|
99
|
+
decode_response(res)
|
100
|
+
rescue EOFError
|
101
|
+
connect
|
102
|
+
retry
|
103
|
+
rescue => ex
|
104
|
+
puts "#{__method__}: #{ex}, sleep for 1 second and retry"
|
105
|
+
sleep(1)
|
106
|
+
retry
|
107
|
+
end
|
108
|
+
|
109
|
+
def put_json(path, object)
|
110
|
+
data = JSON.generate(object)
|
111
|
+
puts "# PUT #{url(path)} #{data}"
|
112
|
+
req = Net::HTTP::Put.new(path)
|
113
|
+
req['content-type'] = "application/json"
|
114
|
+
setup_request(req)
|
115
|
+
res = @client.request(req, data)
|
116
|
+
decode_response(res)
|
117
|
+
rescue EOFError
|
118
|
+
connect
|
119
|
+
retry
|
120
|
+
rescue => ex
|
121
|
+
puts "#{__method__}: #{ex}, sleep for 1 second and retry"
|
122
|
+
sleep(1)
|
123
|
+
retry
|
124
|
+
end
|
125
|
+
|
126
|
+
def delete(path)
|
127
|
+
puts "# DELETE #{url(path)}"
|
128
|
+
req = Net::HTTP::Delete.new(path)
|
129
|
+
setup_request(req)
|
130
|
+
res = @client.request(req)
|
131
|
+
decode_response(res)
|
132
|
+
rescue EOFError
|
133
|
+
connect
|
134
|
+
retry
|
135
|
+
rescue => ex
|
136
|
+
puts "#{__method__}: #{ex}, sleep for 1 second and retry"
|
137
|
+
sleep(1)
|
138
|
+
retry
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def service_address_for_bucket(api, service, bucket, options)
|
143
|
+
port_key = options[:strict_encryption] ? "#{service}SSL" : service
|
144
|
+
host = nil
|
145
|
+
port = 0
|
146
|
+
while port.zero?
|
147
|
+
config = api.get("/pools/default/b/#{bucket}")
|
148
|
+
node_with_service = config["nodesExt"].find{|n| n["services"].key?(port_key)} rescue nil
|
149
|
+
if node_with_service
|
150
|
+
host = node_with_service["hostname"]
|
151
|
+
port = node_with_service["services"][port_key].to_i rescue 0
|
152
|
+
end
|
153
|
+
sleep 1
|
154
|
+
end
|
155
|
+
{host: host || options[:host], port: port}
|
156
|
+
end
|
157
|
+
|
158
|
+
def ensure_search_index_created(index_definition_path, options)
|
159
|
+
loop do
|
160
|
+
catch :retry do
|
161
|
+
search_api = API.new(options)
|
162
|
+
|
163
|
+
puts "using index definition: #{File.basename(index_definition_path)}"
|
164
|
+
index_definition = JSON.load(File.read(index_definition_path))
|
165
|
+
search_api.put_json("/api/index/travel-sample-index", index_definition)
|
166
|
+
|
167
|
+
expected_number_of_the_documents = 1000
|
168
|
+
indexed_documents = 0
|
169
|
+
times_zero_documents_has_been_seen = 0
|
170
|
+
Timeout.timeout(10 * 60) do # give it 10 minutes to index
|
171
|
+
while indexed_documents < expected_number_of_the_documents
|
172
|
+
resp = search_api.get("/api/index/travel-sample-index/count")
|
173
|
+
indexed_documents = resp['count'].to_i
|
174
|
+
times_zero_documents_has_been_seen += 1 if indexed_documents.zero?
|
175
|
+
if times_zero_documents_has_been_seen >= 60
|
176
|
+
# lets not tolerate 60 seconds of not getting data indexed
|
177
|
+
search_api.delete("/api/index/travel-sample-index")
|
178
|
+
throw :retry
|
179
|
+
end
|
180
|
+
sleep 1
|
181
|
+
end
|
182
|
+
end
|
183
|
+
return
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def ensure_sample_bucket_loaded(management_api, expected_number_of_the_documents, options)
|
189
|
+
loop do
|
190
|
+
catch :retry do
|
191
|
+
management_api.post_json("/sampleBuckets/install", [options[:bucket]])
|
192
|
+
|
193
|
+
service_address = nil
|
194
|
+
begin
|
195
|
+
Timeout.timeout(60) do # a minute for bucket creation
|
196
|
+
service_address = service_address_for_bucket(management_api, "n1ql", options[:bucket], options)
|
197
|
+
end
|
198
|
+
rescue Timeout::Error
|
199
|
+
management_api.delete("/pools/default/buckets/#{options[:bucket]}")
|
200
|
+
sleep 1
|
201
|
+
throw :retry
|
202
|
+
end
|
203
|
+
puts query_service: service_address
|
204
|
+
|
205
|
+
query_api = API.new(options.merge(service_address))
|
206
|
+
puts "create index for bucket \"#{options[:bucket]}\""
|
207
|
+
|
208
|
+
query_api.post_form("/query/service", statement: "CREATE PRIMARY INDEX ON `#{options[:bucket]}` USING GSI", timeout: "300s")
|
209
|
+
|
210
|
+
indexed_documents = 0
|
211
|
+
times_zero_documents_has_been_seen = 0
|
212
|
+
Timeout.timeout(10 * 60) do # give it 10 minutes to index
|
213
|
+
while indexed_documents < expected_number_of_the_documents
|
214
|
+
resp = query_api.post_form("/query/service", statement: "SELECT RAW COUNT(*) FROM `#{options[:bucket]}`")
|
215
|
+
indexed_documents = resp["results"][0].to_i rescue 0
|
216
|
+
|
217
|
+
if indexed_documents.zero?
|
218
|
+
times_zero_documents_has_been_seen += 1
|
219
|
+
puts times_zero_documents_has_been_seen: times_zero_documents_has_been_seen
|
220
|
+
end
|
221
|
+
if times_zero_documents_has_been_seen >= 60
|
222
|
+
# lets not tolerate 60 seconds of not getting data indexed
|
223
|
+
query_api.post_form("/query/service", statement: "DROP PRIMARY INDEX ON `#{options[:bucket]}`")
|
224
|
+
management_api.delete("/pools/default/buckets/#{options[:bucket]}")
|
225
|
+
sleep 1
|
226
|
+
throw :retry
|
227
|
+
end
|
228
|
+
sleep 1
|
229
|
+
end
|
230
|
+
end
|
231
|
+
return
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
@@ -15,150 +15,33 @@
|
|
15
15
|
# limitations under the License.
|
16
16
|
|
17
17
|
require "timeout"
|
18
|
-
require "net/http"
|
19
|
-
require "json"
|
20
|
-
require "openssl"
|
21
18
|
|
22
|
-
|
23
|
-
def initialize(options)
|
24
|
-
@options = options
|
25
|
-
connect
|
26
|
-
end
|
27
|
-
|
28
|
-
def connect
|
29
|
-
puts "# CONNECT #{@options}"
|
30
|
-
@client = Net::HTTP.start(@options[:host], @options[:port],
|
31
|
-
use_ssl: @options[:strict_encryption],
|
32
|
-
verify_mode: OpenSSL::SSL::VERIFY_NONE)
|
33
|
-
end
|
34
|
-
|
35
|
-
def url(path)
|
36
|
-
"#{@client.use_ssl? ? 'https' : 'http'}://#{@options[:username]}@#{@options[:host]}:#{@options[:port]}#{path}"
|
37
|
-
end
|
38
|
-
|
39
|
-
def decode_response(response)
|
40
|
-
payload =
|
41
|
-
if response['content-type'] =~ /application\/json/
|
42
|
-
JSON.parse(response.body)
|
43
|
-
else
|
44
|
-
response.body
|
45
|
-
end
|
46
|
-
p payload if @options[:verbose]
|
47
|
-
payload
|
48
|
-
end
|
49
|
-
|
50
|
-
def setup_request(request)
|
51
|
-
request.basic_auth(@options[:username], @options[:password])
|
52
|
-
request['accept'] = "application/json"
|
53
|
-
end
|
54
|
-
|
55
|
-
def get(path)
|
56
|
-
puts "# GET #{url(path)}"
|
57
|
-
req = Net::HTTP::Get.new(path)
|
58
|
-
setup_request(req)
|
59
|
-
res = @client.request(req)
|
60
|
-
decode_response(res)
|
61
|
-
rescue EOFError
|
62
|
-
connect
|
63
|
-
retry
|
64
|
-
rescue => ex
|
65
|
-
puts "#{__method__}: #{ex}, sleep for 1 second and retry"
|
66
|
-
sleep(1)
|
67
|
-
retry
|
68
|
-
end
|
69
|
-
|
70
|
-
def post_form(path, fields = {})
|
71
|
-
puts "# POST #{url(path)} #{fields}"
|
72
|
-
req = Net::HTTP::Post.new(path)
|
73
|
-
setup_request(req)
|
74
|
-
req.form_data = fields
|
75
|
-
res = @client.request(req)
|
76
|
-
decode_response(res)
|
77
|
-
rescue EOFError
|
78
|
-
connect
|
79
|
-
retry
|
80
|
-
rescue => ex
|
81
|
-
puts "#{__method__}: #{ex}, sleep for 1 second and retry"
|
82
|
-
sleep(1)
|
83
|
-
retry
|
84
|
-
end
|
85
|
-
|
86
|
-
def post_json(path, object)
|
87
|
-
data = JSON.generate(object)
|
88
|
-
puts "# POST #{url(path)} #{data}"
|
89
|
-
req = Net::HTTP::Post.new(path)
|
90
|
-
req['content-type'] = "application/json"
|
91
|
-
setup_request(req)
|
92
|
-
res = @client.request(req, data)
|
93
|
-
decode_response(res)
|
94
|
-
rescue EOFError
|
95
|
-
connect
|
96
|
-
retry
|
97
|
-
rescue => ex
|
98
|
-
puts "#{__method__}: #{ex}, sleep for 1 second and retry"
|
99
|
-
sleep(1)
|
100
|
-
retry
|
101
|
-
end
|
102
|
-
|
103
|
-
def put_json(path, object)
|
104
|
-
data = JSON.generate(object)
|
105
|
-
puts "# PUT #{url(path)} #{data}"
|
106
|
-
req = Net::HTTP::Put.new(path)
|
107
|
-
req['content-type'] = "application/json"
|
108
|
-
setup_request(req)
|
109
|
-
res = @client.request(req, data)
|
110
|
-
decode_response(res)
|
111
|
-
rescue EOFError
|
112
|
-
connect
|
113
|
-
retry
|
114
|
-
rescue => ex
|
115
|
-
puts "#{__method__}: #{ex}, sleep for 1 second and retry"
|
116
|
-
sleep(1)
|
117
|
-
retry
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
def service_port_for_bucket(api, service, bucket, options)
|
122
|
-
port_key = options[:strict_encryption] ? "#{service}SSL" : service
|
123
|
-
port = 0
|
124
|
-
while port.zero?
|
125
|
-
config = api.get("/pools/default/b/#{bucket}")
|
126
|
-
port = config["nodesExt"].find{|n| n["services"].key?(port_key)}["services"][port_key].to_i rescue 0
|
127
|
-
sleep 1
|
128
|
-
end
|
129
|
-
port
|
130
|
-
end
|
19
|
+
require_relative "api"
|
131
20
|
|
132
21
|
options = {
|
133
|
-
host: ARGV[0] || "127.0.0.1",
|
134
|
-
strict_encryption:
|
135
|
-
username: ARGV[2] || "Administrator",
|
136
|
-
password: ARGV[3] || "password",
|
22
|
+
host: ENV.fetch("CB_HOST", ARGV[0] || "127.0.0.1"),
|
23
|
+
strict_encryption: ENV.fetch("CB_STRICT_ENCRYPTION", ARGV[1]).to_b,
|
24
|
+
username: ENV.fetch("CB_USERNAME", ARGV[2] || "Administrator"),
|
25
|
+
password: ENV.fetch("CB_PASSWORD", ARGV[3] || "password"),
|
26
|
+
verbose: ENV.fetch("CB_VERBOSE", true).to_b,
|
137
27
|
bucket: "travel-sample",
|
138
|
-
verbose: true,
|
139
28
|
}
|
140
29
|
p options: options
|
141
30
|
|
142
|
-
management_api =
|
143
|
-
|
31
|
+
management_api =
|
32
|
+
begin
|
33
|
+
API.new(options.merge(port: options[:strict_encryption] ? 18091 : 8091))
|
34
|
+
rescue => ex
|
35
|
+
puts "#{ex}, sleep for 1 second and retry"
|
36
|
+
sleep(1)
|
37
|
+
retry
|
38
|
+
end
|
39
|
+
service_address = service_address_for_bucket(management_api, "fts", options[:bucket], options)
|
40
|
+
p search_service: service_address
|
144
41
|
|
145
|
-
has_v6_nodes =
|
42
|
+
has_v6_nodes =
|
146
43
|
management_api.get("/pools/default")["nodes"]
|
147
44
|
.any? { |node| node["version"] =~ /^6\./ && node["services"].include?("fts") }
|
148
45
|
|
149
|
-
search_api = API.new(options.merge(port: search_service_port))
|
150
46
|
index_definition_path = File.join(__dir__, "travel-sample-index#{"-v6" if has_v6_nodes}.json")
|
151
|
-
|
152
|
-
index_definition = JSON.load(File.read(index_definition_path))
|
153
|
-
search_api.put_json("/api/index/travel-sample-index", index_definition)
|
154
|
-
|
155
|
-
expected_number_of_the_documents = 1000
|
156
|
-
indexed_documents = 0
|
157
|
-
|
158
|
-
Timeout.timeout(10 * 60) do # give it 10 minutes to index
|
159
|
-
while indexed_documents < expected_number_of_the_documents
|
160
|
-
resp = search_api.get("/api/index/travel-sample-index/count")
|
161
|
-
indexed_documents = resp['count'].to_i
|
162
|
-
sleep 1
|
163
|
-
end
|
164
|
-
end
|
47
|
+
ensure_search_index_created(index_definition_path, options.merge(service_address))
|
@@ -17,13 +17,8 @@
|
|
17
17
|
require "set"
|
18
18
|
require "timeout"
|
19
19
|
require "optparse"
|
20
|
-
require "openssl"
|
21
20
|
|
22
|
-
|
23
|
-
def to_b
|
24
|
-
![nil, false, 0, "", "0", "f", "F", "false", "FALSE", "off", "OFF", "no", "NO"].include?(self)
|
25
|
-
end
|
26
|
-
end
|
21
|
+
require_relative "api"
|
27
22
|
|
28
23
|
options = {
|
29
24
|
verbose: ENV.fetch("CB_VERBOSE", true).to_b,
|
@@ -49,106 +44,6 @@ options[:port] = ENV.fetch("CB_PORT", default_port).to_i
|
|
49
44
|
options[:sample_buckets] << "beer-sample" if ENV.fetch("CB_BEER_SAMPLE", false).to_b
|
50
45
|
options[:sample_buckets] << "travel-sample" if ENV.fetch("CB_TRAVEL_SAMPLE", false).to_b
|
51
46
|
|
52
|
-
require "net/http"
|
53
|
-
require "json"
|
54
|
-
|
55
|
-
class API
|
56
|
-
def initialize(options)
|
57
|
-
@options = options
|
58
|
-
connect
|
59
|
-
end
|
60
|
-
|
61
|
-
def connect
|
62
|
-
@client = Net::HTTP.start(@options[:host], @options[:port],
|
63
|
-
use_ssl: @options[:strict_encryption],
|
64
|
-
verify_mode: OpenSSL::SSL::VERIFY_NONE)
|
65
|
-
end
|
66
|
-
|
67
|
-
def url(path)
|
68
|
-
"#{@client.use_ssl? ? 'https' : 'http'}://#{@options[:username]}@#{@options[:host]}:#{@options[:port]}#{path}"
|
69
|
-
end
|
70
|
-
|
71
|
-
def decode_response(response)
|
72
|
-
payload =
|
73
|
-
if /application\/json/.match?(response['content-type'])
|
74
|
-
JSON.parse(response.body)
|
75
|
-
else
|
76
|
-
response.body
|
77
|
-
end
|
78
|
-
p payload if @options[:verbose]
|
79
|
-
payload
|
80
|
-
end
|
81
|
-
|
82
|
-
def setup_request(request)
|
83
|
-
request.basic_auth(@options[:username], @options[:password])
|
84
|
-
request['accept'] = "application/json"
|
85
|
-
end
|
86
|
-
|
87
|
-
def get(path)
|
88
|
-
puts "# GET #{url(path)}"
|
89
|
-
req = Net::HTTP::Get.new(path)
|
90
|
-
setup_request(req)
|
91
|
-
res = @client.request(req)
|
92
|
-
decode_response(res)
|
93
|
-
rescue EOFError
|
94
|
-
connect
|
95
|
-
retry
|
96
|
-
rescue => ex
|
97
|
-
puts "#{__method__}: #{ex}, sleep for 1 second and retry"
|
98
|
-
sleep(1)
|
99
|
-
retry
|
100
|
-
end
|
101
|
-
|
102
|
-
def post_form(path, fields = {})
|
103
|
-
puts "# POST #{url(path)} #{fields}"
|
104
|
-
req = Net::HTTP::Post.new(path)
|
105
|
-
setup_request(req)
|
106
|
-
req.form_data = fields
|
107
|
-
res = @client.request(req)
|
108
|
-
decode_response(res)
|
109
|
-
rescue EOFError
|
110
|
-
connect
|
111
|
-
retry
|
112
|
-
rescue => ex
|
113
|
-
puts "#{__method__}: #{ex}, sleep for 1 second and retry"
|
114
|
-
sleep(1)
|
115
|
-
retry
|
116
|
-
end
|
117
|
-
|
118
|
-
def post_json(path, object)
|
119
|
-
data = JSON.generate(object)
|
120
|
-
puts "# POST #{url(path)} #{data}"
|
121
|
-
req = Net::HTTP::Post.new(path)
|
122
|
-
req['content-type'] = "application/json"
|
123
|
-
setup_request(req)
|
124
|
-
res = @client.request(req, data)
|
125
|
-
decode_response(res)
|
126
|
-
rescue EOFError
|
127
|
-
connect
|
128
|
-
retry
|
129
|
-
rescue => ex
|
130
|
-
puts "#{__method__}: #{ex}, sleep for 1 second and retry"
|
131
|
-
sleep(1)
|
132
|
-
retry
|
133
|
-
end
|
134
|
-
|
135
|
-
def put_json(path, object)
|
136
|
-
data = JSON.generate(object)
|
137
|
-
puts "# PUT #{url(path)} #{data}"
|
138
|
-
req = Net::HTTP::Put.new(path)
|
139
|
-
req['content-type'] = "application/json"
|
140
|
-
setup_request(req)
|
141
|
-
res = @client.request(req, data)
|
142
|
-
decode_response(res)
|
143
|
-
rescue EOFError
|
144
|
-
connect
|
145
|
-
retry
|
146
|
-
rescue => ex
|
147
|
-
puts "#{__method__}: #{ex}, sleep for 1 second and retry"
|
148
|
-
sleep(1)
|
149
|
-
retry
|
150
|
-
end
|
151
|
-
end
|
152
47
|
|
153
48
|
api =
|
154
49
|
begin
|
@@ -180,7 +75,10 @@ api.post_form("/settings/web",
|
|
180
75
|
password: options[:password],
|
181
76
|
username: options[:username],
|
182
77
|
port: "SAME")
|
183
|
-
api.post_form("/settings/indexes", storageMode: "plasma")
|
78
|
+
res = api.post_form("/settings/indexes", storageMode: "plasma")
|
79
|
+
if res["errors"]
|
80
|
+
res = api.post_form("/settings/indexes", storageMode: "forestdb")
|
81
|
+
end
|
184
82
|
|
185
83
|
if options[:cluster_run_nodes] > 1
|
186
84
|
known_nodes = []
|
@@ -235,50 +133,30 @@ if options[:sec_bucket].to_b
|
|
235
133
|
name: options[:sec_bucket])
|
236
134
|
end
|
237
135
|
|
238
|
-
api.post_json("/sampleBuckets/install", options[:sample_buckets].to_a) if options[:sample_buckets].any?
|
239
|
-
|
240
136
|
api.post_form("/settings/developerPreview", enabled: true) if options[:enable_developer_preview]
|
241
137
|
|
242
|
-
|
243
|
-
|
244
|
-
port = 0
|
245
|
-
while port.zero?
|
246
|
-
config = api.get("/pools/default/b/#{bucket}")
|
247
|
-
port = config["nodesExt"].find{|n| n["services"].key?(port_key)}["services"][port_key].to_i rescue 0
|
248
|
-
sleep 1
|
249
|
-
end
|
250
|
-
port
|
251
|
-
end
|
138
|
+
service_address = service_address_for_bucket(api, "n1ql", options[:bucket], options)
|
139
|
+
puts query_service: service_address
|
252
140
|
|
253
|
-
query_api = API.new(options.merge(
|
141
|
+
query_api = API.new(options.merge(service_address))
|
254
142
|
query_api.post_form("/query/service", statement: "CREATE PRIMARY INDEX ON `#{options[:bucket]}` USING GSI")
|
143
|
+
|
144
|
+
expected_counts = {
|
145
|
+
"travel-sample" => 30_000,
|
146
|
+
"beer-sample" => 7_000,
|
147
|
+
}
|
255
148
|
options[:sample_buckets].each do |bucket|
|
256
|
-
|
257
|
-
query_api.post_form("/query/service", statement: "CREATE PRIMARY INDEX ON `#{bucket}` USING GSI")
|
149
|
+
ensure_sample_bucket_loaded(api, expected_counts[bucket], options.merge(bucket: bucket))
|
258
150
|
end
|
259
151
|
|
260
|
-
puts service_port_for_bucket(api, "fts", options[:bucket], options)
|
261
|
-
|
262
152
|
if options[:sample_buckets].include?("travel-sample") && services.include?("fts")
|
263
|
-
|
153
|
+
service_address = service_address_for_bucket(api, "fts", options[:bucket], options)
|
154
|
+
puts search_service: service_address
|
264
155
|
|
265
156
|
has_v6_nodes =
|
266
157
|
api.get("/pools/default")["nodes"]
|
267
158
|
.any? { |node| node["version"] =~ /^6\./ && node["services"].include?("fts") }
|
268
|
-
|
269
159
|
index_definition_path = File.join(__dir__, "travel-sample-index#{"-v6" if has_v6_nodes}.json")
|
270
|
-
|
271
|
-
index_definition = JSON.load(File.read(index_definition_path))
|
272
|
-
search_api.put_json("/api/index/travel-sample-index", index_definition)
|
273
|
-
|
274
|
-
expected_number_of_the_documents = 1000
|
275
|
-
indexed_documents = 0
|
276
|
-
Timeout.timeout(10 * 60) do # give it 10 minutes to index
|
277
|
-
while indexed_documents < expected_number_of_the_documents
|
278
|
-
resp = search_api.get("/api/index/travel-sample-index/count")
|
279
|
-
indexed_documents = resp['count'].to_i
|
280
|
-
sleep 1
|
281
|
-
end
|
282
|
-
end
|
160
|
+
ensure_search_index_created(index_definition_path, options.merge(service_address))
|
283
161
|
end
|
284
162
|
|