connectors_service 8.6.0.4 → 8.7.0.0.pre.20221117T010623Z
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 +4 -4
- data/config/connectors.yml +9 -8
- data/lib/app/app.rb +4 -0
- data/lib/app/config.rb +3 -0
- data/lib/app/dispatcher.rb +44 -17
- data/lib/app/preflight_check.rb +11 -0
- data/lib/connectors/base/advanced_snippet_against_schema_validator.rb +173 -0
- data/lib/connectors/base/advanced_snippet_validator.rb +34 -0
- data/lib/connectors/base/connector.rb +43 -14
- data/lib/connectors/base/simple_rules_parser.rb +42 -0
- data/lib/connectors/example/connector.rb +6 -0
- data/lib/connectors/example/example_advanced_snippet_validator.rb +35 -0
- data/lib/connectors/gitlab/connector.rb +6 -1
- data/lib/connectors/gitlab/gitlab_advanced_snippet_validator.rb +35 -0
- data/lib/connectors/mongodb/connector.rb +47 -43
- data/lib/connectors/mongodb/mongo_advanced_snippet_against_schema_validator.rb +22 -0
- data/lib/connectors/mongodb/mongo_advanced_snippet_schema.rb +292 -0
- data/lib/connectors/mongodb/mongo_rules_parser.rb +81 -0
- data/lib/connectors/sync_status.rb +6 -1
- data/lib/connectors/tolerable_error_helper.rb +43 -0
- data/lib/connectors_app/// +13 -0
- data/lib/core/configuration.rb +3 -1
- data/lib/core/connector_job.rb +210 -0
- data/lib/core/connector_settings.rb +52 -16
- data/lib/core/elastic_connector_actions.rb +320 -59
- data/lib/core/filtering/post_process_engine.rb +39 -0
- data/lib/core/filtering/post_process_result.rb +27 -0
- data/lib/core/filtering/simple_rule.rb +141 -0
- data/lib/core/filtering/validation_job_runner.rb +53 -0
- data/lib/core/filtering/validation_status.rb +17 -0
- data/lib/core/filtering.rb +17 -0
- data/lib/core/ingestion/es_sink.rb +118 -0
- data/lib/core/{output_sink.rb → ingestion.rb} +1 -5
- data/lib/core/jobs/consumer.rb +132 -0
- data/lib/core/jobs/producer.rb +26 -0
- data/lib/core/scheduler.rb +40 -10
- data/lib/core/single_scheduler.rb +1 -1
- data/lib/core/sync_job_runner.rb +80 -16
- data/lib/core.rb +4 -0
- data/lib/utility/bulk_queue.rb +87 -0
- data/lib/utility/constants.rb +7 -0
- data/lib/utility/error_monitor.rb +108 -0
- data/lib/utility/errors.rb +0 -12
- data/lib/utility/filtering.rb +22 -0
- data/lib/utility/logger.rb +1 -1
- data/lib/utility.rb +11 -4
- metadata +31 -12
- data/lib/core/output_sink/base_sink.rb +0 -33
- data/lib/core/output_sink/combined_sink.rb +0 -38
- data/lib/core/output_sink/console_sink.rb +0 -51
- data/lib/core/output_sink/es_sink.rb +0 -74
@@ -7,6 +7,9 @@
|
|
7
7
|
# frozen_string_literal: true
|
8
8
|
|
9
9
|
require 'connectors/base/connector'
|
10
|
+
require 'core/filtering/validation_status'
|
11
|
+
require 'connectors/mongodb/mongo_rules_parser'
|
12
|
+
require 'connectors/mongodb/mongo_advanced_snippet_against_schema_validator'
|
10
13
|
require 'mongo'
|
11
14
|
require 'utility'
|
12
15
|
|
@@ -28,27 +31,31 @@ module Connectors
|
|
28
31
|
|
29
32
|
def self.configurable_fields
|
30
33
|
{
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
34
|
+
:host => {
|
35
|
+
:label => 'Server Hostname'
|
36
|
+
},
|
37
|
+
:user => {
|
38
|
+
:label => 'Username'
|
39
|
+
},
|
40
|
+
:password => {
|
41
|
+
:label => 'Password'
|
42
|
+
},
|
43
|
+
:database => {
|
44
|
+
:label => 'Database'
|
45
|
+
},
|
46
|
+
:collection => {
|
47
|
+
:label => 'Collection'
|
48
|
+
},
|
49
|
+
:direct_connection => {
|
50
|
+
:label => 'Direct connection? (true/false)'
|
51
|
+
}
|
49
52
|
}
|
50
53
|
end
|
51
54
|
|
55
|
+
def self.advanced_snippet_validator
|
56
|
+
MongoAdvancedSnippetAgainstSchemaValidator
|
57
|
+
end
|
58
|
+
|
52
59
|
def initialize(configuration: {}, job_description: {})
|
53
60
|
super
|
54
61
|
|
@@ -61,8 +68,6 @@ module Connectors
|
|
61
68
|
end
|
62
69
|
|
63
70
|
def yield_documents
|
64
|
-
check_filtering
|
65
|
-
|
66
71
|
with_client do |client|
|
67
72
|
# We do paging using skip().limit() here to make Ruby recycle the memory for each page pulled from the server after it's not needed any more.
|
68
73
|
# This gives us more control on the usage of the memory (we can adjust PAGE_SIZE constant for that to decrease max memory consumption).
|
@@ -89,15 +94,15 @@ module Connectors
|
|
89
94
|
loop do
|
90
95
|
found_in_page = 0
|
91
96
|
|
97
|
+
Utility::Logger.info("Requesting #{PAGE_SIZE} documents from MongoDB (Starting at #{skip})")
|
92
98
|
view = cursor.skip(skip).limit(PAGE_SIZE)
|
93
99
|
view.each do |document|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
100
|
+
yield_with_handling_tolerable_errors do
|
101
|
+
yield serialize(document)
|
102
|
+
found_in_page += 1
|
103
|
+
found_overall += 1
|
104
|
+
overall_limit_reached = found_overall >= overall_limit && overall_limit != Float::INFINITY
|
105
|
+
end
|
101
106
|
break if overall_limit_reached
|
102
107
|
end
|
103
108
|
|
@@ -117,20 +122,9 @@ module Connectors
|
|
117
122
|
|
118
123
|
return create_aggregate_cursor(collection) if @advanced_filter_config[:aggregate].present?
|
119
124
|
|
120
|
-
collection.
|
121
|
-
end
|
122
|
-
|
123
|
-
def check_filtering
|
124
|
-
return unless filtering_present?
|
125
|
+
return create_simple_rules_cursor(collection) if @rules.present?
|
125
126
|
|
126
|
-
|
127
|
-
end
|
128
|
-
|
129
|
-
def check_find_and_aggregate
|
130
|
-
if @advanced_filter_config.keys.size != 1
|
131
|
-
invalid_keys_msg = "Only one of #{ALLOWED_TOP_LEVEL_FILTER_KEYS} is allowed in the filtering object. Keys present: '#{@advanced_filter_config.keys}'."
|
132
|
-
raise Utility::InvalidFilterConfigError.new(invalid_keys_msg)
|
133
|
-
end
|
127
|
+
collection.find
|
134
128
|
end
|
135
129
|
|
136
130
|
def create_aggregate_cursor(collection)
|
@@ -159,6 +153,16 @@ module Connectors
|
|
159
153
|
[collection.find(filter, options), options]
|
160
154
|
end
|
161
155
|
|
156
|
+
def create_simple_rules_cursor(collection)
|
157
|
+
filter = {}
|
158
|
+
if @rules.present?
|
159
|
+
parser = MongoRulesParser.new(@rules)
|
160
|
+
filter = parser.parse
|
161
|
+
end
|
162
|
+
Utility::Logger.info("Filtering with simple rules filter: #{filter}")
|
163
|
+
filter.present? ? collection.find(filter) : collection.find
|
164
|
+
end
|
165
|
+
|
162
166
|
def extract_options(mongodb_function)
|
163
167
|
mongodb_function[:options].present? ? mongodb_function[:options] : {}
|
164
168
|
end
|
@@ -173,9 +177,9 @@ module Connectors
|
|
173
177
|
raise "Invalid value for 'Direct connection' : #{@direct_connection}." unless %w[true false].include?(@direct_connection.to_s.strip.downcase)
|
174
178
|
|
175
179
|
args = {
|
176
|
-
|
177
|
-
|
178
|
-
|
180
|
+
database: @database,
|
181
|
+
direct_connection: to_boolean(@direct_connection)
|
182
|
+
}
|
179
183
|
|
180
184
|
if @user.present? || @password.present?
|
181
185
|
args[:user] = @user
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#
|
2
|
+
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
3
|
+
# or more contributor license agreements. Licensed under the Elastic License;
|
4
|
+
# you may not use this file except in compliance with the Elastic License.
|
5
|
+
#
|
6
|
+
|
7
|
+
# frozen_string_literal: true
|
8
|
+
|
9
|
+
require 'connectors/base/advanced_snippet_against_schema_validator'
|
10
|
+
require 'connectors/mongodb/mongo_advanced_snippet_schema'
|
11
|
+
|
12
|
+
module Connectors
|
13
|
+
module MongoDB
|
14
|
+
class MongoAdvancedSnippetAgainstSchemaValidator < Connectors::Base::AdvancedSnippetAgainstSchemaValidator
|
15
|
+
|
16
|
+
def initialize(advanced_snippet, schema = Connectors::MongoDB::AdvancedSnippet::SCHEMA)
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,292 @@
|
|
1
|
+
#
|
2
|
+
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
3
|
+
# or more contributor license agreements. Licensed under the Elastic License;
|
4
|
+
# you may not use this file except in compliance with the Elastic License.
|
5
|
+
#
|
6
|
+
|
7
|
+
# frozen_string_literal: true
|
8
|
+
|
9
|
+
module Connectors
|
10
|
+
module MongoDB
|
11
|
+
module AdvancedSnippet
|
12
|
+
# Pipeline stages: https://www.mongodb.com/docs/manual/reference/operator/aggregation-pipeline/
|
13
|
+
ALLOWED_PIPELINE_STAGES = %w[
|
14
|
+
$addFields $bucket $bucketAuto $changeStream $collStats $count $densify
|
15
|
+
$documents $facet $fill $geoNear $graphLookup $group $indexStats $limit
|
16
|
+
$listSessions $lookup $match $merge $out $planCacheStats $project $redact
|
17
|
+
$replaceRoot $replaceWith $sample $search $searchMeta $set $setWindowFields
|
18
|
+
$skip $sort $sortByCount $unionWith $unset $unwind
|
19
|
+
]
|
20
|
+
|
21
|
+
# All except the $out, $merge, $geoNear, and $changeStream stages can appear multiple times in a pipeline.
|
22
|
+
# Source: https://www.mongodb.com/docs/manual/reference/operator/aggregation-pipeline/
|
23
|
+
PIPELINE_STAGES_ALLOWED_ONCE = %w[$out $merge $geoNear $changeStream]
|
24
|
+
|
25
|
+
NON_NEGATIVE_INTEGER = ->(value) { value.is_a?(Integer) && value >= 0 }
|
26
|
+
READ_CONCERN_LEVEL = ->(level) { %w[local available majority linearizable].include?(level) }
|
27
|
+
STRING_OR_DOCUMENT = ->(value) { value.is_a?(Hash) || value.is_a?(String) }
|
28
|
+
MUTUAL_EXCLUSIVE_FILTER = ->(fields) { fields.size <= 1 }
|
29
|
+
|
30
|
+
AGGREGATION_PIPELINE = lambda { |pipeline|
|
31
|
+
return false unless pipeline.is_a?(Array)
|
32
|
+
|
33
|
+
allowed_once_appearances = Set.new
|
34
|
+
|
35
|
+
pipeline.flat_map(&:keys).each do |key|
|
36
|
+
return false unless ALLOWED_PIPELINE_STAGES.include?(key)
|
37
|
+
|
38
|
+
if PIPELINE_STAGES_ALLOWED_ONCE.include?(key)
|
39
|
+
return false if allowed_once_appearances.include?(key)
|
40
|
+
|
41
|
+
allowed_once_appearances.add(key)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
true
|
46
|
+
}
|
47
|
+
|
48
|
+
# Ruby has no 'Boolean' class
|
49
|
+
BOOLEAN = ->(value) { value.is_a?(TrueClass) || value.is_a?(FalseClass) }
|
50
|
+
|
51
|
+
COLLATION = {
|
52
|
+
:name => 'collation',
|
53
|
+
:type => Hash,
|
54
|
+
:optional => true,
|
55
|
+
:fields => [
|
56
|
+
{
|
57
|
+
:name => 'locale',
|
58
|
+
:type => String,
|
59
|
+
:optional => true
|
60
|
+
},
|
61
|
+
{
|
62
|
+
:name => 'caseLevel',
|
63
|
+
:type => BOOLEAN,
|
64
|
+
:optional => true
|
65
|
+
},
|
66
|
+
{
|
67
|
+
:name => 'caseFirst',
|
68
|
+
:type => String,
|
69
|
+
:optional => true
|
70
|
+
},
|
71
|
+
{
|
72
|
+
:name => 'strength',
|
73
|
+
:type => Integer,
|
74
|
+
:optional => true
|
75
|
+
},
|
76
|
+
{
|
77
|
+
:name => 'numericOrdering',
|
78
|
+
:type => BOOLEAN,
|
79
|
+
:optional => true
|
80
|
+
},
|
81
|
+
{
|
82
|
+
:name => 'alternate',
|
83
|
+
:type => String,
|
84
|
+
:optional => true
|
85
|
+
},
|
86
|
+
{
|
87
|
+
:name => 'maxVariable',
|
88
|
+
:type => String,
|
89
|
+
:optional => true
|
90
|
+
},
|
91
|
+
{
|
92
|
+
:name => 'backwards',
|
93
|
+
:type => BOOLEAN,
|
94
|
+
:optional => true
|
95
|
+
},
|
96
|
+
]
|
97
|
+
}
|
98
|
+
|
99
|
+
CURSOR_TYPE = ->(cursor) { [:tailable, :tailable_await].include?(cursor) }
|
100
|
+
|
101
|
+
# Aggregate options: https://www.mongodb.com/docs/manual/reference/method/db.collection.aggregate/
|
102
|
+
AGGREGATE_OPTIONS = {
|
103
|
+
:name => 'options',
|
104
|
+
:type => Hash,
|
105
|
+
:optional => true,
|
106
|
+
:fields => [
|
107
|
+
{
|
108
|
+
:name => 'explain',
|
109
|
+
:type => BOOLEAN,
|
110
|
+
:optional => true
|
111
|
+
},
|
112
|
+
{
|
113
|
+
:name => 'allowDiskUse',
|
114
|
+
:type => BOOLEAN,
|
115
|
+
:optional => true
|
116
|
+
},
|
117
|
+
{
|
118
|
+
:name => 'cursor',
|
119
|
+
:type => Hash,
|
120
|
+
:optional => true,
|
121
|
+
:fields => [
|
122
|
+
{
|
123
|
+
:name => 'batchSize',
|
124
|
+
:type => NON_NEGATIVE_INTEGER
|
125
|
+
}
|
126
|
+
]
|
127
|
+
},
|
128
|
+
{
|
129
|
+
:name => 'maxTimeMS',
|
130
|
+
:type => NON_NEGATIVE_INTEGER,
|
131
|
+
:optional => true
|
132
|
+
},
|
133
|
+
{
|
134
|
+
:name => 'bypassDocumentValidation',
|
135
|
+
:type => BOOLEAN,
|
136
|
+
:optional => true
|
137
|
+
},
|
138
|
+
{
|
139
|
+
:name => 'readConcern',
|
140
|
+
:type => Hash,
|
141
|
+
:optional => true,
|
142
|
+
:fields => [
|
143
|
+
{
|
144
|
+
:name => 'level',
|
145
|
+
:type => READ_CONCERN_LEVEL
|
146
|
+
}
|
147
|
+
]
|
148
|
+
},
|
149
|
+
COLLATION,
|
150
|
+
{
|
151
|
+
:name => 'hint',
|
152
|
+
:type => STRING_OR_DOCUMENT,
|
153
|
+
:optional => true
|
154
|
+
},
|
155
|
+
{
|
156
|
+
:name => 'comment',
|
157
|
+
:type => String,
|
158
|
+
:optional => true
|
159
|
+
},
|
160
|
+
{
|
161
|
+
:name => 'writeConcern',
|
162
|
+
:type => Hash,
|
163
|
+
:optional => true
|
164
|
+
},
|
165
|
+
{
|
166
|
+
:name => 'let',
|
167
|
+
:type => Hash,
|
168
|
+
:optional => true
|
169
|
+
}
|
170
|
+
]
|
171
|
+
}
|
172
|
+
|
173
|
+
AGGREGATE_PIPELINE = {
|
174
|
+
:name => 'pipeline',
|
175
|
+
:type => AGGREGATION_PIPELINE,
|
176
|
+
:optional => true,
|
177
|
+
}
|
178
|
+
|
179
|
+
AGGREGATE = {
|
180
|
+
:name => 'aggregate',
|
181
|
+
:type => Hash,
|
182
|
+
:optional => true,
|
183
|
+
:fields => [
|
184
|
+
AGGREGATE_PIPELINE,
|
185
|
+
AGGREGATE_OPTIONS
|
186
|
+
]
|
187
|
+
}
|
188
|
+
|
189
|
+
FIND_OPTIONS = {
|
190
|
+
:name => 'options',
|
191
|
+
:type => Hash,
|
192
|
+
:optional => true,
|
193
|
+
:fields => [
|
194
|
+
{
|
195
|
+
:name => 'allowDiskUse',
|
196
|
+
:type => BOOLEAN,
|
197
|
+
:optional => true
|
198
|
+
},
|
199
|
+
{
|
200
|
+
:name => 'allowPartialResults',
|
201
|
+
:type => BOOLEAN,
|
202
|
+
:optional => true
|
203
|
+
},
|
204
|
+
{
|
205
|
+
:name => 'batchSize',
|
206
|
+
:type => NON_NEGATIVE_INTEGER,
|
207
|
+
:optional => true
|
208
|
+
},
|
209
|
+
COLLATION,
|
210
|
+
{
|
211
|
+
:name => 'cursorType',
|
212
|
+
:type => CURSOR_TYPE,
|
213
|
+
:optional => true
|
214
|
+
},
|
215
|
+
{
|
216
|
+
:name => 'limit',
|
217
|
+
:type => NON_NEGATIVE_INTEGER,
|
218
|
+
:optional => true
|
219
|
+
},
|
220
|
+
{
|
221
|
+
:name => 'maxTimeMS',
|
222
|
+
:type => NON_NEGATIVE_INTEGER,
|
223
|
+
:optional => true
|
224
|
+
},
|
225
|
+
{
|
226
|
+
:name => 'modifiers',
|
227
|
+
:type => Hash,
|
228
|
+
:optional => true
|
229
|
+
},
|
230
|
+
{
|
231
|
+
:name => 'noCursorTimeout',
|
232
|
+
:type => BOOLEAN,
|
233
|
+
:optional => true
|
234
|
+
},
|
235
|
+
{
|
236
|
+
:name => 'oplogReplay',
|
237
|
+
:type => BOOLEAN,
|
238
|
+
:optional => true
|
239
|
+
},
|
240
|
+
{
|
241
|
+
:name => 'projection',
|
242
|
+
:type => Hash,
|
243
|
+
:optional => true
|
244
|
+
},
|
245
|
+
{
|
246
|
+
:name => 'skip',
|
247
|
+
:type => NON_NEGATIVE_INTEGER,
|
248
|
+
:optional => true
|
249
|
+
},
|
250
|
+
{
|
251
|
+
:name => 'sort',
|
252
|
+
:type => Hash,
|
253
|
+
:optional => true
|
254
|
+
},
|
255
|
+
{
|
256
|
+
:name => 'let',
|
257
|
+
:type => Hash,
|
258
|
+
:optional => true
|
259
|
+
}
|
260
|
+
]
|
261
|
+
}
|
262
|
+
|
263
|
+
# TODO: return true for now. Will be more involved (basically needs full query parsing or "dummy" execution against a running instance)
|
264
|
+
FILTER = ->(_filter) { true }
|
265
|
+
|
266
|
+
FIND_FILTER = {
|
267
|
+
:name => 'filter',
|
268
|
+
:type => FILTER
|
269
|
+
}
|
270
|
+
|
271
|
+
FIND = {
|
272
|
+
:name => 'find',
|
273
|
+
:type => Hash,
|
274
|
+
:optional => true,
|
275
|
+
:fields => [
|
276
|
+
FIND_OPTIONS,
|
277
|
+
FIND_FILTER
|
278
|
+
]
|
279
|
+
}
|
280
|
+
|
281
|
+
SCHEMA = {
|
282
|
+
:fields => {
|
283
|
+
:constraints => MUTUAL_EXCLUSIVE_FILTER,
|
284
|
+
:values => [
|
285
|
+
AGGREGATE,
|
286
|
+
FIND
|
287
|
+
]
|
288
|
+
}
|
289
|
+
}
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#
|
2
|
+
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
3
|
+
# or more contributor license agreements. Licensed under the Elastic License;
|
4
|
+
# you may not use this file except in compliance with the Elastic License.
|
5
|
+
#
|
6
|
+
|
7
|
+
# frozen_string_literal: true
|
8
|
+
|
9
|
+
require 'active_support/core_ext/object'
|
10
|
+
require 'connectors/base/simple_rules_parser'
|
11
|
+
require 'core/filtering/simple_rule'
|
12
|
+
|
13
|
+
module Connectors
|
14
|
+
module MongoDB
|
15
|
+
class MongoRulesParser < Connectors::Base::SimpleRulesParser
|
16
|
+
def parse_rule(rule)
|
17
|
+
field = rule.field
|
18
|
+
value = rule.value
|
19
|
+
unless value.present?
|
20
|
+
raise "value is required for field: #{field}"
|
21
|
+
end
|
22
|
+
unless field.present?
|
23
|
+
raise "field is required for rule: #{rule}"
|
24
|
+
end
|
25
|
+
op = rule.rule
|
26
|
+
case op
|
27
|
+
when Core::Filtering::SimpleRule::Rule::EQUALS
|
28
|
+
parse_equals(rule)
|
29
|
+
when Core::Filtering::SimpleRule::Rule::GREATER_THAN
|
30
|
+
parse_greater_than(rule)
|
31
|
+
when Core::Filtering::SimpleRule::Rule::LESS_THAN
|
32
|
+
parse_less_than(rule)
|
33
|
+
when Core::Filtering::SimpleRule::Rule::REGEX
|
34
|
+
parse_regex(rule)
|
35
|
+
else
|
36
|
+
raise "Unknown operator: #{op}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def merge_rules(rules)
|
41
|
+
return {} if rules.empty?
|
42
|
+
return rules[0] if rules.size == 1
|
43
|
+
{ '$and' => rules }
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def parse_equals(rule)
|
49
|
+
if rule.is_include?
|
50
|
+
{ rule.field => rule.value }
|
51
|
+
else
|
52
|
+
{ rule.field => { '$ne' => rule.value } }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_greater_than(rule)
|
57
|
+
if rule.is_include?
|
58
|
+
{ rule.field => { '$gt' => rule.value } }
|
59
|
+
else
|
60
|
+
{ rule.field => { '$lte' => rule.value } }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def parse_less_than(rule)
|
65
|
+
if rule.is_include?
|
66
|
+
{ rule.field => { '$lt' => rule.value } }
|
67
|
+
else
|
68
|
+
{ rule.field => { '$gte' => rule.value } }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def parse_regex(rule)
|
73
|
+
if rule.is_include?
|
74
|
+
{ rule.field => /#{rule.value}/ }
|
75
|
+
else
|
76
|
+
{ rule.field => { '$not' => /#{rule.value}/ } }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
3
|
+
# or more contributor license agreements. Licensed under the Elastic License;
|
4
|
+
# you may not use this file except in compliance with the Elastic License.
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'utility/logger'
|
8
|
+
require 'utility/exception_tracking'
|
9
|
+
require 'utility/error_monitor'
|
10
|
+
|
11
|
+
module Connectors
|
12
|
+
class TolerableErrorHelper
|
13
|
+
def initialize(error_monitor)
|
14
|
+
@error_monitor = error_monitor
|
15
|
+
end
|
16
|
+
|
17
|
+
def yield_single_document(identifier: nil)
|
18
|
+
Utility::Logger.debug("Extracting single document for #{identifier}") if identifier
|
19
|
+
yield
|
20
|
+
@error_monitor.note_success
|
21
|
+
rescue *fatal_exception_classes => e
|
22
|
+
Utility::ExceptionTracking.augment_exception(e)
|
23
|
+
Utility::Logger.error("Encountered a fall-through error during extraction#{identifying_error_message(identifier)}: #{e.class}: #{e.message} {:message_id => #{e.id}}")
|
24
|
+
raise
|
25
|
+
rescue StandardError => e
|
26
|
+
Utility::ExceptionTracking.augment_exception(e)
|
27
|
+
Utility::Logger.warn("Encountered error during extraction#{identifying_error_message(identifier)}: #{e.class}: #{e.message} {:message_id => #{e.id}}")
|
28
|
+
@error_monitor.note_error(e, :id => e.id)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def identifying_error_message(identifier)
|
34
|
+
identifier.present? ? " of '#{identifier}'" : ''
|
35
|
+
end
|
36
|
+
|
37
|
+
def fatal_exception_classes
|
38
|
+
[
|
39
|
+
Utility::ErrorMonitor::MonitoringError
|
40
|
+
]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#
|
2
|
+
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
3
|
+
# or more contributor license agreements. Licensed under the Elastic License;
|
4
|
+
# you may not use this file except in compliance with the Elastic License.
|
5
|
+
#
|
6
|
+
|
7
|
+
module ConnectorsApp
|
8
|
+
module Errors
|
9
|
+
INVALID_API_KEY = 'INVALID_API_KEY'
|
10
|
+
UNSUPPORTED_AUTH_SCHEME = 'UNSUPPORTED_AUTH_SCHEME'
|
11
|
+
INTERNAL_SERVER_ERROR = 'INTERNAL_SERVER_ERROR'
|
12
|
+
end
|
13
|
+
end
|
data/lib/core/configuration.rb
CHANGED
@@ -24,8 +24,10 @@ module Core
|
|
24
24
|
return
|
25
25
|
end
|
26
26
|
configuration = connector_class.configurable_fields_indifferent_access
|
27
|
+
features = connector_class.kibana_features.each_with_object({}) { |feature, hsh| hsh[feature] = true }
|
27
28
|
doc = {
|
28
|
-
:configuration => configuration
|
29
|
+
:configuration => configuration,
|
30
|
+
:features => features
|
29
31
|
}
|
30
32
|
|
31
33
|
doc[:service_type] = service_type if service_type && connector_settings.needs_service_type?
|