avro_turf 1.4.1 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0d201b8d402f0d88f3ce125040de4e056d0125607b6988236ff076b3fd042569
4
- data.tar.gz: 0c1cbad2263b35f56dc04ca2def7a9ec520a3c95952acbc27f544a1c96337de8
3
+ metadata.gz: 3eea429db02f7f6eba5f13f46b2bf3e82602371ef9306e374c1102561f508675
4
+ data.tar.gz: d798ef10b0e674f48ffdcc6bd3b87e59d9447c985d539f2ba01164e689fe4f8a
5
5
  SHA512:
6
- metadata.gz: 3af9af40e690c6033afb5183d9438ff0785e09a8ac2288873df20f7f50cfd4c439d05dd227d5655e91e490630f4cb677b9ef167be66af072816a07bd2ef1d7a6
7
- data.tar.gz: 0d440453c9c8ac12aa3cfc07b9348de674e29fbed65809cbf47956468d2c28b62223f213ffa1f1db2726a96cc0707be98e4cb3cc4bfbb0b4229a7982d529a235
6
+ metadata.gz: e7cacb60d4e7890a700ebaba9a0cf1d46606fb01157e0746a0d6a6c900895e9ca1268f0a04dd4d03f5d1a9cec9bf6795d9c5d70acb6884965353c72bb1de4095
7
+ data.tar.gz: c4dbd604b66916355a6cba44ec4e7225eb439c2d9bb0682e62414b6ffa3018bb1d2a84b78d943983c99d7af3897a67658db9cb2205f7d92d6c13661ae44ba602
data/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## v1.7.0
6
+
7
+ - Added extra params for the validation message schem before encode (#169)
8
+ - Fix infinite retry when loading schema with nested primary type in separate file (#165)
9
+
10
+ ## v1.6.0
11
+
12
+ - Schema registry path prefix (#162)
13
+
14
+ ## v1.5.0
15
+
16
+ - Add CA cert file option (#157)
17
+ - Add compatibility with Avro v1.11.x.
18
+
5
19
  ## v1.4.1
6
20
 
7
21
  - Purge sub-schemas from cache before re-parsing schema (#151)
data/avro_turf.gemspec CHANGED
@@ -12,12 +12,14 @@ Gem::Specification.new do |spec|
12
12
  spec.homepage = "https://github.com/dasch/avro_turf"
13
13
  spec.license = "MIT"
14
14
 
15
+ spec.metadata["rubygems_mfa_required"] = "true"
16
+
15
17
  spec.files = `git ls-files -z`.split("\x0")
16
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
20
  spec.require_paths = ["lib"]
19
21
 
20
- spec.add_dependency "avro", ">= 1.7.7", "< 1.11"
22
+ spec.add_dependency "avro", ">= 1.7.7", "< 1.12"
21
23
  spec.add_dependency "excon", "~> 0.71"
22
24
 
23
25
  spec.add_development_dependency "bundler", "~> 2.0"
@@ -9,12 +9,15 @@ class AvroTurf::ConfluentSchemaRegistry
9
9
  proxy: nil,
10
10
  user: nil,
11
11
  password: nil,
12
+ ssl_ca_file: nil,
12
13
  client_cert: nil,
13
14
  client_key: nil,
14
15
  client_key_pass: nil,
15
16
  client_cert_data: nil,
16
- client_key_data: nil
17
+ client_key_data: nil,
18
+ path_prefix: nil
17
19
  )
20
+ @path_prefix = path_prefix
18
21
  @logger = logger
19
22
  headers = {
20
23
  "Content-Type" => CONTENT_TYPE
@@ -25,6 +28,7 @@ class AvroTurf::ConfluentSchemaRegistry
25
28
  headers: headers,
26
29
  user: user,
27
30
  password: password,
31
+ ssl_ca_file: ssl_ca_file,
28
32
  client_cert: client_cert,
29
33
  client_key: client_key,
30
34
  client_key_pass: client_key_pass,
@@ -120,6 +124,7 @@ class AvroTurf::ConfluentSchemaRegistry
120
124
 
121
125
  def request(path, **options)
122
126
  options = { expects: 200 }.merge!(options)
127
+ path = File.join(@path_prefix, path) unless @path_prefix.nil?
123
128
  response = @connection.request(path: path, **options)
124
129
  JSON.parse(response.body)
125
130
  end
@@ -26,31 +26,35 @@ class AvroTurf
26
26
 
27
27
  # Instantiate a new Messaging instance with the given configuration.
28
28
  #
29
- # registry - A schema registry object that responds to all methods in the
30
- # AvroTurf::ConfluentSchemaRegistry interface.
31
- # registry_url - The String URL of the schema registry that should be used.
32
- # schema_store - A schema store object that responds to #find(schema_name, namespace).
33
- # schemas_path - The String file system path where local schemas are stored.
34
- # namespace - The String default schema namespace.
35
- # logger - The Logger that should be used to log information (optional).
36
- # proxy - Forward the request via proxy (optional).
37
- # user - User for basic auth (optional).
38
- # password - Password for basic auth (optional).
39
- # client_cert - Name of file containing client certificate (optional).
40
- # client_key - Name of file containing client private key to go with client_cert (optional).
41
- # client_key_pass - Password to go with client_key (optional).
42
- # client_cert_data - In-memory client certificate (optional).
43
- # client_key_data - In-memory client private key to go with client_cert_data (optional).
29
+ # registry - A schema registry object that responds to all methods in the
30
+ # AvroTurf::ConfluentSchemaRegistry interface.
31
+ # registry_url - The String URL of the schema registry that should be used.
32
+ # schema_store - A schema store object that responds to #find(schema_name, namespace).
33
+ # schemas_path - The String file system path where local schemas are stored.
34
+ # namespace - The String default schema namespace.
35
+ # registry_path_prefix - The String URL path prefix used to namespace schema registry requests (optional).
36
+ # logger - The Logger that should be used to log information (optional).
37
+ # proxy - Forward the request via proxy (optional).
38
+ # user - User for basic auth (optional).
39
+ # password - Password for basic auth (optional).
40
+ # ssl_ca_file - Name of file containing CA certificate (optional).
41
+ # client_cert - Name of file containing client certificate (optional).
42
+ # client_key - Name of file containing client private key to go with client_cert (optional).
43
+ # client_key_pass - Password to go with client_key (optional).
44
+ # client_cert_data - In-memory client certificate (optional).
45
+ # client_key_data - In-memory client private key to go with client_cert_data (optional).
44
46
  def initialize(
45
47
  registry: nil,
46
48
  registry_url: nil,
47
49
  schema_store: nil,
48
50
  schemas_path: nil,
49
51
  namespace: nil,
52
+ registry_path_prefix: nil,
50
53
  logger: nil,
51
54
  proxy: nil,
52
55
  user: nil,
53
56
  password: nil,
57
+ ssl_ca_file: nil,
54
58
  client_cert: nil,
55
59
  client_key: nil,
56
60
  client_key_pass: nil,
@@ -67,11 +71,13 @@ class AvroTurf
67
71
  proxy: proxy,
68
72
  user: user,
69
73
  password: password,
74
+ ssl_ca_file: ssl_ca_file,
70
75
  client_cert: client_cert,
71
76
  client_key: client_key,
72
77
  client_key_pass: client_key_pass,
73
78
  client_cert_data: client_cert_data,
74
- client_key_data: client_key_data
79
+ client_key_data: client_key_data,
80
+ path_prefix: registry_path_prefix
75
81
  )
76
82
  )
77
83
  @schemas_by_id = {}
@@ -88,7 +88,7 @@ class AvroTurf::SchemaStore
88
88
  local_schemas_cache.each do |schema_name, schema|
89
89
  local_schemas_cache.delete(schema_name) unless File.exist?(build_schema_path(schema_name))
90
90
  end
91
- load_schema!(fullname, local_schemas_cache)
91
+ load_schema!(fullname, @schemas.dup)
92
92
  else
93
93
  raise
94
94
  end
@@ -0,0 +1,102 @@
1
+ require 'sinatra/base'
2
+
3
+ class FakePrefixedConfluentSchemaRegistryServer < FakeConfluentSchemaRegistryServer
4
+ post "/prefix/subjects/:subject/versions" do
5
+ schema = parse_schema
6
+ ids_for_subject = SUBJECTS[params[:subject]]
7
+
8
+ schemas_for_subject =
9
+ SCHEMAS.select
10
+ .with_index { |_, i| ids_for_subject.include?(i) }
11
+
12
+ if schemas_for_subject.include?(schema)
13
+ schema_id = SCHEMAS.index(schema)
14
+ else
15
+ SCHEMAS << schema
16
+ schema_id = SCHEMAS.size - 1
17
+ SUBJECTS[params[:subject]] = SUBJECTS[params[:subject]] << schema_id
18
+ end
19
+
20
+ { id: schema_id }.to_json
21
+ end
22
+
23
+ get "/prefix/schemas/ids/:schema_id" do
24
+ schema = SCHEMAS.at(params[:schema_id].to_i)
25
+ halt(404, SCHEMA_NOT_FOUND) unless schema
26
+ { schema: schema }.to_json
27
+ end
28
+
29
+ get "/prefix/subjects" do
30
+ SUBJECTS.keys.to_json
31
+ end
32
+
33
+ get "/prefix/subjects/:subject/versions" do
34
+ schema_ids = SUBJECTS[params[:subject]]
35
+ halt(404, SUBJECT_NOT_FOUND) if schema_ids.empty?
36
+ (1..schema_ids.size).to_a.to_json
37
+ end
38
+
39
+ get "/prefix/subjects/:subject/versions/:version" do
40
+ schema_ids = SUBJECTS[params[:subject]]
41
+ halt(404, SUBJECT_NOT_FOUND) if schema_ids.empty?
42
+
43
+ schema_id = if params[:version] == 'latest'
44
+ schema_ids.last
45
+ else
46
+ schema_ids.at(Integer(params[:version]) - 1)
47
+ end
48
+ halt(404, VERSION_NOT_FOUND) unless schema_id
49
+
50
+ schema = SCHEMAS.at(schema_id)
51
+
52
+ {
53
+ name: params[:subject],
54
+ version: schema_ids.index(schema_id) + 1,
55
+ id: schema_id,
56
+ schema: schema
57
+ }.to_json
58
+ end
59
+
60
+ post "/prefix/subjects/:subject" do
61
+ schema = parse_schema
62
+
63
+ # Note: this does not actually handle the same schema registered under
64
+ # multiple subjects
65
+ schema_id = SCHEMAS.index(schema)
66
+
67
+ halt(404, SCHEMA_NOT_FOUND) unless schema_id
68
+
69
+ {
70
+ subject: params[:subject],
71
+ id: schema_id,
72
+ version: SUBJECTS[params[:subject]].index(schema_id) + 1,
73
+ schema: schema
74
+ }.to_json
75
+ end
76
+
77
+ post "/prefix/compatibility/subjects/:subject/versions/:version" do
78
+ # The ruby avro gem does not yet include a compatibility check between schemas.
79
+ # See https://github.com/apache/avro/pull/170
80
+ raise NotImplementedError
81
+ end
82
+
83
+ get "/prefix/config" do
84
+ global_config.to_json
85
+ end
86
+
87
+ put "/prefix/config" do
88
+ global_config.merge!(parse_config).to_json
89
+ end
90
+
91
+ get "/prefix/config/:subject" do
92
+ CONFIGS.fetch(params[:subject], global_config).to_json
93
+ end
94
+
95
+ put "/prefix/config/:subject" do
96
+ config = parse_config
97
+ subject = params[:subject]
98
+ CONFIGS.fetch(subject) do
99
+ CONFIGS[subject] = {}
100
+ end.merge!(config).to_json
101
+ end
102
+ end
@@ -1,3 +1,3 @@
1
1
  class AvroTurf
2
- VERSION = "1.4.1"
2
+ VERSION = "1.7.0"
3
3
  end
data/lib/avro_turf.rb CHANGED
@@ -16,7 +16,9 @@ end
16
16
 
17
17
  class AvroTurf
18
18
  class Error < StandardError; end
19
+
19
20
  class SchemaError < Error; end
21
+
20
22
  class SchemaNotFoundError < Error; end
21
23
 
22
24
  DEFAULT_SCHEMAS_PATH = "./schemas"
@@ -31,7 +33,7 @@ class AvroTurf
31
33
  # Currently, the only valid codec name is `deflate`.
32
34
  def initialize(schemas_path: nil, schema_store: nil, namespace: nil, codec: nil)
33
35
  @namespace = namespace
34
- @schema_store = schema_store ||
36
+ @schema_store = schema_store ||
35
37
  SchemaStore.new(path: schemas_path || DEFAULT_SCHEMAS_PATH)
36
38
  @codec = codec
37
39
  end
@@ -62,14 +64,20 @@ class AvroTurf
62
64
  # validate - The boolean for performing complete data validation before
63
65
  # encoding it, Avro::SchemaValidator::ValidationError with
64
66
  # a descriptive message will be raised in case of invalid message.
67
+ # validate_options - Hash for the Avro::SchemaValidator, default
68
+ # {recursive: true, encoded: false, fail_on_extra_fields: true}
65
69
  #
66
70
  # Returns nothing.
67
- def encode_to_stream(data, schema_name: nil, stream: nil, namespace: @namespace, validate: false)
71
+ def encode_to_stream(data, schema_name: nil, stream: nil, namespace: @namespace,
72
+ validate: false,
73
+ validate_options: { recursive: true,
74
+ encoded: false,
75
+ fail_on_extra_fields: true })
68
76
  schema = @schema_store.find(schema_name, namespace)
69
77
  writer = Avro::IO::DatumWriter.new(schema)
70
78
 
71
79
  if validate
72
- Avro::SchemaValidator.validate!(schema, data, recursive: true, encoded: false, fail_on_extra_fields: true)
80
+ Avro::SchemaValidator.validate!(schema, data, **validate_options)
73
81
  end
74
82
 
75
83
  dw = Avro::DataFile::Writer.new(stream, writer, schema, @codec)
@@ -251,6 +251,31 @@ describe AvroTurf do
251
251
  expect { encode_to_stream }.to raise_error(Avro::SchemaValidator::ValidationError, /extra field 'fulll_name'/)
252
252
  end
253
253
  end
254
+
255
+ context "when the `fail_on_extra_fields` validation option is disabled" do
256
+ let(:message) { { "full_name" => "John Doe", "first_name" => "John", "last_name" => "Doe" } }
257
+ subject(:encode_to_stream) do
258
+ stream = StringIO.new
259
+ avro.encode_to_stream(message, stream: stream, schema_name: "message",
260
+ validate: true,
261
+ validate_options: { recursive: true, encoded: false, fail_on_extra_fields: false }
262
+ )
263
+ end
264
+
265
+ it "should not raise Avro::SchemaValidator::ValidationError with a message about extra field" do
266
+ define_schema "message.avsc", <<-AVSC
267
+ {
268
+ "name": "message",
269
+ "type": "record",
270
+ "fields": [
271
+ { "name": "full_name", "type": "string" }
272
+ ]
273
+ }
274
+ AVSC
275
+
276
+ expect { encode_to_stream }.not_to raise_error
277
+ end
278
+ end
254
279
  end
255
280
  end
256
281
 
@@ -1,6 +1,7 @@
1
1
  require 'webmock/rspec'
2
2
  require 'avro_turf/messaging'
3
3
  require 'avro_turf/test/fake_confluent_schema_registry_server'
4
+ require 'avro_turf/test/fake_prefixed_confluent_schema_registry_server'
4
5
 
5
6
  describe AvroTurf::Messaging do
6
7
  let(:registry_url) { "http://registry.example.com" }
@@ -8,7 +9,7 @@ describe AvroTurf::Messaging do
8
9
  let(:client_key) { "test client key" }
9
10
  let(:client_key_pass) { "test client key password" }
10
11
  let(:logger) { Logger.new(StringIO.new) }
11
-
12
+ let(:path_prefix) { nil }
12
13
  let(:avro) {
13
14
  AvroTurf::Messaging.new(
14
15
  registry_url: registry_url,
@@ -72,7 +73,7 @@ describe AvroTurf::Messaging do
72
73
 
73
74
  shared_examples_for 'encoding and decoding with the schema from registry' do
74
75
  before do
75
- registry = AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger)
76
+ registry = AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger, path_prefix: path_prefix)
76
77
  registry.register('person', schema)
77
78
  registry.register('people', schema)
78
79
  end
@@ -102,7 +103,7 @@ describe AvroTurf::Messaging do
102
103
 
103
104
  shared_examples_for 'encoding and decoding with the schema_id from registry' do
104
105
  before do
105
- registry = AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger)
106
+ registry = AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger, path_prefix: path_prefix)
106
107
  registry.register('person', schema)
107
108
  registry.register('people', schema)
108
109
  end
@@ -399,4 +400,29 @@ describe AvroTurf::Messaging do
399
400
  end
400
401
  end
401
402
  end
402
- end
403
+
404
+ context 'with a registry path prefix' do
405
+ let(:path_prefix) { '/prefix' }
406
+
407
+ let(:avro) {
408
+ AvroTurf::Messaging.new(
409
+ registry_path_prefix: path_prefix,
410
+ registry_url: registry_url,
411
+ schemas_path: "spec/schemas",
412
+ logger: logger,
413
+ client_cert: client_cert,
414
+ client_key: client_key,
415
+ client_key_pass: client_key_pass
416
+ )
417
+ }
418
+
419
+ before do
420
+ stub_request(:any, /^#{registry_url}/).to_rack(FakePrefixedConfluentSchemaRegistryServer)
421
+ FakePrefixedConfluentSchemaRegistryServer.clear
422
+ end
423
+
424
+ it_behaves_like "encoding and decoding with the schema from schema store"
425
+ it_behaves_like 'encoding and decoding with the schema from registry'
426
+ it_behaves_like 'encoding and decoding with the schema_id from registry'
427
+ end
428
+ end
@@ -26,6 +26,33 @@ describe AvroTurf::SchemaStore do
26
26
  expect(schema.fullname).to eq "message"
27
27
  end
28
28
 
29
+ it "resolves missing references when nested schema is not a named type" do
30
+ define_schema "root.avsc", <<-AVSC
31
+ {
32
+ "type": "record",
33
+ "name": "root",
34
+ "fields": [
35
+ {
36
+ "type": "nested",
37
+ "name": "nested_value"
38
+ }
39
+ ]
40
+ }
41
+ AVSC
42
+
43
+ define_schema "nested.avsc", <<-AVSC
44
+ {
45
+ "name": "nested",
46
+ "type": "string",
47
+ "logicalType": "uuid"
48
+ }
49
+ AVSC
50
+
51
+ schema = store.find("root")
52
+
53
+ expect(schema.fullname).to eq "root"
54
+ end
55
+
29
56
  it "resolves missing references" do
30
57
  define_schema "person.avsc", <<-AVSC
31
58
  {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: avro_turf
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Schierbeck
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-29 00:00:00.000000000 Z
11
+ date: 2022-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: avro
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: 1.7.7
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '1.11'
22
+ version: '1.12'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: 1.7.7
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '1.11'
32
+ version: '1.12'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: excon
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -156,7 +156,7 @@ dependencies:
156
156
  - - ">="
157
157
  - !ruby/object:Gem::Version
158
158
  version: '0'
159
- description:
159
+ description:
160
160
  email:
161
161
  - dasch@zendesk.com
162
162
  executables: []
@@ -196,6 +196,7 @@ files:
196
196
  - lib/avro_turf/schema_store.rb
197
197
  - lib/avro_turf/schema_to_avro_patch.rb
198
198
  - lib/avro_turf/test/fake_confluent_schema_registry_server.rb
199
+ - lib/avro_turf/test/fake_prefixed_confluent_schema_registry_server.rb
199
200
  - lib/avro_turf/test/fake_schema_registry_server.rb
200
201
  - lib/avro_turf/version.rb
201
202
  - perf/address.avsc
@@ -225,7 +226,8 @@ files:
225
226
  homepage: https://github.com/dasch/avro_turf
226
227
  licenses:
227
228
  - MIT
228
- metadata: {}
229
+ metadata:
230
+ rubygems_mfa_required: 'true'
229
231
  post_install_message: |2
230
232
 
231
233
  avro_turf v0.8.0 deprecates the names AvroTurf::SchemaRegistry,
@@ -249,8 +251,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
249
251
  - !ruby/object:Gem::Version
250
252
  version: '0'
251
253
  requirements: []
252
- rubygems_version: 3.1.2
253
- signing_key:
254
+ rubygems_version: 3.3.3
255
+ signing_key:
254
256
  specification_version: 4
255
257
  summary: A library that makes it easier to use the Avro serialization format from
256
258
  Ruby