rdkafka 0.14.0 → 0.15.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/FUNDING.yml +1 -0
- data/CHANGELOG.md +11 -0
- data/README.md +32 -22
- data/docker-compose.yml +2 -0
- data/lib/rdkafka/admin/acl_binding_result.rb +37 -0
- data/lib/rdkafka/admin/create_acl_handle.rb +28 -0
- data/lib/rdkafka/admin/create_acl_report.rb +24 -0
- data/lib/rdkafka/admin/create_partitions_handle.rb +27 -0
- data/lib/rdkafka/admin/create_partitions_report.rb +6 -0
- data/lib/rdkafka/admin/delete_acl_handle.rb +30 -0
- data/lib/rdkafka/admin/delete_acl_report.rb +23 -0
- data/lib/rdkafka/admin/delete_groups_handle.rb +28 -0
- data/lib/rdkafka/admin/delete_groups_report.rb +24 -0
- data/lib/rdkafka/admin/describe_acl_handle.rb +30 -0
- data/lib/rdkafka/admin/describe_acl_report.rb +23 -0
- data/lib/rdkafka/admin.rb +443 -0
- data/lib/rdkafka/bindings.rb +119 -0
- data/lib/rdkafka/callbacks.rb +187 -0
- data/lib/rdkafka/config.rb +24 -3
- data/lib/rdkafka/consumer/headers.rb +1 -1
- data/lib/rdkafka/consumer/topic_partition_list.rb +8 -7
- data/lib/rdkafka/consumer.rb +46 -10
- data/lib/rdkafka/producer.rb +2 -2
- data/lib/rdkafka/version.rb +3 -3
- data/lib/rdkafka.rb +11 -0
- data/spec/rdkafka/admin/create_acl_handle_spec.rb +56 -0
- data/spec/rdkafka/admin/create_acl_report_spec.rb +18 -0
- data/spec/rdkafka/admin/delete_acl_handle_spec.rb +85 -0
- data/spec/rdkafka/admin/delete_acl_report_spec.rb +71 -0
- data/spec/rdkafka/admin/describe_acl_handle_spec.rb +85 -0
- data/spec/rdkafka/admin/describe_acl_report_spec.rb +72 -0
- data/spec/rdkafka/admin_spec.rb +204 -0
- data/spec/rdkafka/config_spec.rb +8 -0
- data/spec/rdkafka/consumer_spec.rb +69 -0
- data/spec/spec_helper.rb +3 -1
- data.tar.gz.sig +0 -0
- metadata +26 -2
- metadata.gz.sig +0 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe Rdkafka::Admin::DeleteAclReport do
|
6
|
+
|
7
|
+
let(:resource_name) {"acl-test-topic"}
|
8
|
+
let(:resource_type) {Rdkafka::Bindings::RD_KAFKA_RESOURCE_TOPIC}
|
9
|
+
let(:resource_pattern_type) {Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL}
|
10
|
+
let(:principal) {"User:anonymous"}
|
11
|
+
let(:host) {"*"}
|
12
|
+
let(:operation) {Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_READ}
|
13
|
+
let(:permission_type) {Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW}
|
14
|
+
let(:delete_acl_ptr) {FFI::Pointer::NULL}
|
15
|
+
|
16
|
+
subject do
|
17
|
+
error_buffer = FFI::MemoryPointer.from_string(" " * 256)
|
18
|
+
delete_acl_ptr = Rdkafka::Bindings.rd_kafka_AclBinding_new(
|
19
|
+
resource_type,
|
20
|
+
FFI::MemoryPointer.from_string(resource_name),
|
21
|
+
resource_pattern_type,
|
22
|
+
FFI::MemoryPointer.from_string(principal),
|
23
|
+
FFI::MemoryPointer.from_string(host),
|
24
|
+
operation,
|
25
|
+
permission_type,
|
26
|
+
error_buffer,
|
27
|
+
256
|
28
|
+
)
|
29
|
+
if delete_acl_ptr.null?
|
30
|
+
raise Rdkafka::Config::ConfigError.new(error_buffer.read_string)
|
31
|
+
end
|
32
|
+
pointer_array = [delete_acl_ptr]
|
33
|
+
delete_acls_array_ptr = FFI::MemoryPointer.new(:pointer)
|
34
|
+
delete_acls_array_ptr.write_array_of_pointer(pointer_array)
|
35
|
+
Rdkafka::Admin::DeleteAclReport.new(matching_acls: delete_acls_array_ptr, matching_acls_count: 1)
|
36
|
+
end
|
37
|
+
|
38
|
+
after do
|
39
|
+
if delete_acl_ptr != FFI::Pointer::NULL
|
40
|
+
Rdkafka::Bindings.rd_kafka_AclBinding_destroy(delete_acl_ptr)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should get deleted acl resource type as Rdkafka::Bindings::RD_KAFKA_RESOURCE_TOPIC" do
|
45
|
+
expect(subject.deleted_acls[0].matching_acl_resource_type).to eq(Rdkafka::Bindings::RD_KAFKA_RESOURCE_TOPIC)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should get deleted acl resource name as acl-test-topic" do
|
49
|
+
expect(subject.deleted_acls[0].matching_acl_resource_name).to eq(resource_name)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should get deleted acl resource pattern type as Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL" do
|
53
|
+
expect(subject.deleted_acls[0].matching_acl_pattern_type).to eq(Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should get deleted acl principal as User:anonymous" do
|
57
|
+
expect(subject.deleted_acls[0].matching_acl_principal).to eq("User:anonymous")
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should get deleted acl host as * " do
|
61
|
+
expect(subject.deleted_acls[0].matching_acl_host).to eq("*")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should get deleted acl operation as Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_READ" do
|
65
|
+
expect(subject.deleted_acls[0].matching_acl_operation).to eq(Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_READ)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should get deleted acl permission_type as Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW" do
|
69
|
+
expect(subject.deleted_acls[0].matching_acl_permission_type).to eq(Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW)
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe Rdkafka::Admin::DescribeAclHandle do
|
6
|
+
let(:response) { Rdkafka::Bindings::RD_KAFKA_RESP_ERR_NO_ERROR }
|
7
|
+
let(:resource_name) {"acl-test-topic"}
|
8
|
+
let(:resource_type) {Rdkafka::Bindings::RD_KAFKA_RESOURCE_TOPIC}
|
9
|
+
let(:resource_pattern_type) {Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL}
|
10
|
+
let(:principal) {"User:anonymous"}
|
11
|
+
let(:host) {"*"}
|
12
|
+
let(:operation) {Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_READ}
|
13
|
+
let(:permission_type) {Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW}
|
14
|
+
let(:describe_acl_ptr) {FFI::Pointer::NULL}
|
15
|
+
|
16
|
+
subject do
|
17
|
+
error_buffer = FFI::MemoryPointer.from_string(" " * 256)
|
18
|
+
describe_acl_ptr = Rdkafka::Bindings.rd_kafka_AclBinding_new(
|
19
|
+
resource_type,
|
20
|
+
FFI::MemoryPointer.from_string(resource_name),
|
21
|
+
resource_pattern_type,
|
22
|
+
FFI::MemoryPointer.from_string(principal),
|
23
|
+
FFI::MemoryPointer.from_string(host),
|
24
|
+
operation,
|
25
|
+
permission_type,
|
26
|
+
error_buffer,
|
27
|
+
256
|
28
|
+
)
|
29
|
+
if describe_acl_ptr.null?
|
30
|
+
raise Rdkafka::Config::ConfigError.new(error_buffer.read_string)
|
31
|
+
end
|
32
|
+
pointer_array = [describe_acl_ptr]
|
33
|
+
describe_acls_array_ptr = FFI::MemoryPointer.new(:pointer)
|
34
|
+
describe_acls_array_ptr.write_array_of_pointer(pointer_array)
|
35
|
+
Rdkafka::Admin::DescribeAclHandle.new.tap do |handle|
|
36
|
+
handle[:pending] = pending_handle
|
37
|
+
handle[:response] = response
|
38
|
+
handle[:response_string] = FFI::MemoryPointer.from_string("")
|
39
|
+
handle[:acls] = describe_acls_array_ptr
|
40
|
+
handle[:acls_count] = 1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
after do
|
45
|
+
if describe_acl_ptr != FFI::Pointer::NULL
|
46
|
+
Rdkafka::Bindings.rd_kafka_AclBinding_destroy(describe_acl_ptr)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#wait" do
|
51
|
+
let(:pending_handle) { true }
|
52
|
+
|
53
|
+
it "should wait until the timeout and then raise an error" do
|
54
|
+
expect {
|
55
|
+
subject.wait(max_wait_timeout: 0.1)
|
56
|
+
}.to raise_error Rdkafka::Admin::DescribeAclHandle::WaitTimeoutError, /describe acl/
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when not pending anymore and no error" do
|
60
|
+
let(:pending_handle) { false }
|
61
|
+
|
62
|
+
it "should return a describe acl report" do
|
63
|
+
report = subject.wait
|
64
|
+
|
65
|
+
expect(report.acls.length).to eq(1)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should wait without a timeout" do
|
69
|
+
report = subject.wait(max_wait_timeout: nil)
|
70
|
+
|
71
|
+
expect(report.acls[0].matching_acl_resource_name).to eq("acl-test-topic")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "#raise_error" do
|
77
|
+
let(:pending_handle) { false }
|
78
|
+
|
79
|
+
it "should raise the appropriate error" do
|
80
|
+
expect {
|
81
|
+
subject.raise_error
|
82
|
+
}.to raise_exception(Rdkafka::RdkafkaError, /Success \(no_error\)/)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe Rdkafka::Admin::DescribeAclReport do
|
6
|
+
|
7
|
+
let(:resource_name) {"acl-test-topic"}
|
8
|
+
let(:resource_type) {Rdkafka::Bindings::RD_KAFKA_RESOURCE_TOPIC}
|
9
|
+
let(:resource_pattern_type) {Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL}
|
10
|
+
let(:principal) {"User:anonymous"}
|
11
|
+
let(:host) {"*"}
|
12
|
+
let(:operation) {Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_READ}
|
13
|
+
let(:permission_type) {Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW}
|
14
|
+
let(:describe_acl_ptr) {FFI::Pointer::NULL}
|
15
|
+
|
16
|
+
subject do
|
17
|
+
error_buffer = FFI::MemoryPointer.from_string(" " * 256)
|
18
|
+
describe_acl_ptr = Rdkafka::Bindings.rd_kafka_AclBinding_new(
|
19
|
+
resource_type,
|
20
|
+
FFI::MemoryPointer.from_string(resource_name),
|
21
|
+
resource_pattern_type,
|
22
|
+
FFI::MemoryPointer.from_string(principal),
|
23
|
+
FFI::MemoryPointer.from_string(host),
|
24
|
+
operation,
|
25
|
+
permission_type,
|
26
|
+
error_buffer,
|
27
|
+
256
|
28
|
+
)
|
29
|
+
if describe_acl_ptr.null?
|
30
|
+
raise Rdkafka::Config::ConfigError.new(error_buffer.read_string)
|
31
|
+
end
|
32
|
+
pointer_array = [describe_acl_ptr]
|
33
|
+
describe_acls_array_ptr = FFI::MemoryPointer.new(:pointer)
|
34
|
+
describe_acls_array_ptr.write_array_of_pointer(pointer_array)
|
35
|
+
Rdkafka::Admin::DescribeAclReport.new(acls: describe_acls_array_ptr, acls_count: 1)
|
36
|
+
end
|
37
|
+
|
38
|
+
after do
|
39
|
+
if describe_acl_ptr != FFI::Pointer::NULL
|
40
|
+
Rdkafka::Bindings.rd_kafka_AclBinding_destroy(describe_acl_ptr)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
it "should get matching acl resource type as Rdkafka::Bindings::RD_KAFKA_RESOURCE_TOPIC" do
|
46
|
+
expect(subject.acls[0].matching_acl_resource_type).to eq(Rdkafka::Bindings::RD_KAFKA_RESOURCE_TOPIC)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should get matching acl resource name as acl-test-topic" do
|
50
|
+
expect(subject.acls[0].matching_acl_resource_name).to eq(resource_name)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should get matching acl resource pattern type as Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL" do
|
54
|
+
expect(subject.acls[0].matching_acl_pattern_type).to eq(Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should get matching acl principal as User:anonymous" do
|
58
|
+
expect(subject.acls[0].matching_acl_principal).to eq("User:anonymous")
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should get matching acl host as * " do
|
62
|
+
expect(subject.acls[0].matching_acl_host).to eq("*")
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should get matching acl operation as Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_READ" do
|
66
|
+
expect(subject.acls[0].matching_acl_operation).to eq(Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_READ)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should get matching acl permission_type as Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW" do
|
70
|
+
expect(subject.acls[0].matching_acl_permission_type).to eq(Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW)
|
71
|
+
end
|
72
|
+
end
|
data/spec/rdkafka/admin_spec.rb
CHANGED
@@ -9,6 +9,10 @@ describe Rdkafka::Admin do
|
|
9
9
|
after do
|
10
10
|
# Registry should always end up being empty
|
11
11
|
expect(Rdkafka::Admin::CreateTopicHandle::REGISTRY).to be_empty
|
12
|
+
expect(Rdkafka::Admin::CreatePartitionsHandle::REGISTRY).to be_empty
|
13
|
+
expect(Rdkafka::Admin::DescribeAclHandle::REGISTRY).to be_empty
|
14
|
+
expect(Rdkafka::Admin::CreateAclHandle::REGISTRY).to be_empty
|
15
|
+
expect(Rdkafka::Admin::DeleteAclHandle::REGISTRY).to be_empty
|
12
16
|
admin.close
|
13
17
|
end
|
14
18
|
|
@@ -17,6 +21,15 @@ describe Rdkafka::Admin do
|
|
17
21
|
let(:topic_replication_factor) { 1 }
|
18
22
|
let(:topic_config) { {"cleanup.policy" => "compact", "min.cleanable.dirty.ratio" => 0.8} }
|
19
23
|
let(:invalid_topic_config) { {"cleeeeenup.policee" => "campact"} }
|
24
|
+
let(:group_name) { "test-group-#{Random.new.rand(0..1_000_000)}" }
|
25
|
+
|
26
|
+
let(:resource_name) {"acl-test-topic"}
|
27
|
+
let(:resource_type) {Rdkafka::Bindings::RD_KAFKA_RESOURCE_TOPIC}
|
28
|
+
let(:resource_pattern_type) {Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_LITERAL}
|
29
|
+
let(:principal) {"User:anonymous"}
|
30
|
+
let(:host) {"*"}
|
31
|
+
let(:operation) {Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_READ}
|
32
|
+
let(:permission_type) {Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ALLOW}
|
20
33
|
|
21
34
|
describe "#create_topic" do
|
22
35
|
describe "called with invalid input" do
|
@@ -200,4 +213,195 @@ expect(ex.broker_message).to match(/Topic name.*is invalid: .* contains one or m
|
|
200
213
|
expect(delete_topic_report.result_name).to eq(topic_name)
|
201
214
|
end
|
202
215
|
end
|
216
|
+
|
217
|
+
describe "#ACL tests" do
|
218
|
+
let(:non_existing_resource_name) {"non-existing-topic"}
|
219
|
+
before do
|
220
|
+
#create topic for testing acl
|
221
|
+
create_topic_handle = admin.create_topic(resource_name, topic_partition_count, topic_replication_factor)
|
222
|
+
create_topic_report = create_topic_handle.wait(max_wait_timeout: 15.0)
|
223
|
+
end
|
224
|
+
|
225
|
+
after do
|
226
|
+
#delete acl
|
227
|
+
delete_acl_handle = admin.delete_acl(resource_type: resource_type, resource_name: resource_name, resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
|
228
|
+
delete_acl_report = delete_acl_handle.wait(max_wait_timeout: 15.0)
|
229
|
+
|
230
|
+
#delete topic that was created for testing acl
|
231
|
+
delete_topic_handle = admin.delete_topic(resource_name)
|
232
|
+
delete_topic_report = delete_topic_handle.wait(max_wait_timeout: 15.0)
|
233
|
+
end
|
234
|
+
|
235
|
+
describe "#create_acl" do
|
236
|
+
it "create acl for a topic that does not exist" do
|
237
|
+
# acl creation for resources that does not exist will still get created successfully.
|
238
|
+
create_acl_handle = admin.create_acl(resource_type: resource_type, resource_name: non_existing_resource_name, resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
|
239
|
+
create_acl_report = create_acl_handle.wait(max_wait_timeout: 15.0)
|
240
|
+
expect(create_acl_report.rdkafka_response).to eq(0)
|
241
|
+
expect(create_acl_report.rdkafka_response_string).to eq("")
|
242
|
+
|
243
|
+
# delete the acl that was created for a non existing topic"
|
244
|
+
delete_acl_handle = admin.delete_acl(resource_type: resource_type, resource_name: non_existing_resource_name, resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
|
245
|
+
delete_acl_report = delete_acl_handle.wait(max_wait_timeout: 15.0)
|
246
|
+
expect(delete_acl_handle[:response]).to eq(0)
|
247
|
+
expect(delete_acl_report.deleted_acls.size).to eq(1)
|
248
|
+
end
|
249
|
+
|
250
|
+
it "creates a acl for topic that was newly created" do
|
251
|
+
create_acl_handle = admin.create_acl(resource_type: resource_type, resource_name: resource_name, resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
|
252
|
+
create_acl_report = create_acl_handle.wait(max_wait_timeout: 15.0)
|
253
|
+
expect(create_acl_report.rdkafka_response).to eq(0)
|
254
|
+
expect(create_acl_report.rdkafka_response_string).to eq("")
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
describe "#describe_acl" do
|
259
|
+
it "describe acl of a topic that does not exist" do
|
260
|
+
describe_acl_handle = admin.describe_acl(resource_type: resource_type, resource_name: non_existing_resource_name, resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
|
261
|
+
describe_acl_report = describe_acl_handle.wait(max_wait_timeout: 15.0)
|
262
|
+
expect(describe_acl_handle[:response]).to eq(0)
|
263
|
+
expect(describe_acl_report.acls.size).to eq(0)
|
264
|
+
end
|
265
|
+
|
266
|
+
it "create acls and describe the newly created acls" do
|
267
|
+
#create_acl
|
268
|
+
create_acl_handle = admin.create_acl(resource_type: resource_type, resource_name: "test_acl_topic_1", resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
|
269
|
+
create_acl_report = create_acl_handle.wait(max_wait_timeout: 15.0)
|
270
|
+
expect(create_acl_report.rdkafka_response).to eq(0)
|
271
|
+
expect(create_acl_report.rdkafka_response_string).to eq("")
|
272
|
+
|
273
|
+
create_acl_handle = admin.create_acl(resource_type: resource_type, resource_name: "test_acl_topic_2", resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
|
274
|
+
create_acl_report = create_acl_handle.wait(max_wait_timeout: 15.0)
|
275
|
+
expect(create_acl_report.rdkafka_response).to eq(0)
|
276
|
+
expect(create_acl_report.rdkafka_response_string).to eq("")
|
277
|
+
|
278
|
+
#describe_acl
|
279
|
+
describe_acl_handle = admin.describe_acl(resource_type: Rdkafka::Bindings::RD_KAFKA_RESOURCE_ANY, resource_name: nil, resource_pattern_type: Rdkafka::Bindings::RD_KAFKA_RESOURCE_PATTERN_ANY, principal: nil, host: nil, operation: Rdkafka::Bindings::RD_KAFKA_ACL_OPERATION_ANY, permission_type: Rdkafka::Bindings::RD_KAFKA_ACL_PERMISSION_TYPE_ANY)
|
280
|
+
describe_acl_report = describe_acl_handle.wait(max_wait_timeout: 15.0)
|
281
|
+
expect(describe_acl_handle[:response]).to eq(0)
|
282
|
+
expect(describe_acl_report.acls.length).to eq(2)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
describe "#delete_acl" do
|
287
|
+
it "delete acl of a topic that does not exist" do
|
288
|
+
delete_acl_handle = admin.delete_acl(resource_type: resource_type, resource_name: non_existing_resource_name, resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
|
289
|
+
delete_acl_report = delete_acl_handle.wait(max_wait_timeout: 15.0)
|
290
|
+
expect(delete_acl_handle[:response]).to eq(0)
|
291
|
+
expect(delete_acl_report.deleted_acls.size).to eq(0)
|
292
|
+
end
|
293
|
+
|
294
|
+
it "create an acl and delete the newly created acl" do
|
295
|
+
#create_acl
|
296
|
+
create_acl_handle = admin.create_acl(resource_type: resource_type, resource_name: "test_acl_topic_1", resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
|
297
|
+
create_acl_report = create_acl_handle.wait(max_wait_timeout: 15.0)
|
298
|
+
expect(create_acl_report.rdkafka_response).to eq(0)
|
299
|
+
expect(create_acl_report.rdkafka_response_string).to eq("")
|
300
|
+
|
301
|
+
create_acl_handle = admin.create_acl(resource_type: resource_type, resource_name: "test_acl_topic_2", resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
|
302
|
+
create_acl_report = create_acl_handle.wait(max_wait_timeout: 15.0)
|
303
|
+
expect(create_acl_report.rdkafka_response).to eq(0)
|
304
|
+
expect(create_acl_report.rdkafka_response_string).to eq("")
|
305
|
+
|
306
|
+
#delete_acl - resource_name nil - to delete all acls with any resource name and matching all other filters.
|
307
|
+
delete_acl_handle = admin.delete_acl(resource_type: resource_type, resource_name: nil, resource_pattern_type: resource_pattern_type, principal: principal, host: host, operation: operation, permission_type: permission_type)
|
308
|
+
delete_acl_report = delete_acl_handle.wait(max_wait_timeout: 15.0)
|
309
|
+
expect(delete_acl_handle[:response]).to eq(0)
|
310
|
+
expect(delete_acl_report.deleted_acls.length).to eq(2)
|
311
|
+
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
describe('Group tests') do
|
317
|
+
describe "#delete_group" do
|
318
|
+
describe("with an existing group") do
|
319
|
+
let(:consumer_config) { rdkafka_consumer_config('group.id': group_name) }
|
320
|
+
let(:producer_config) { rdkafka_producer_config }
|
321
|
+
let(:producer) { producer_config.producer }
|
322
|
+
let(:consumer) { consumer_config.consumer }
|
323
|
+
|
324
|
+
before do
|
325
|
+
# Create a topic, post a message to it, consume it and commit offsets, this will create a group that we can then delete.
|
326
|
+
admin.create_topic(topic_name, topic_partition_count, topic_replication_factor).wait(max_wait_timeout: 15.0)
|
327
|
+
|
328
|
+
producer.produce(topic: topic_name, payload: "test", key: "test").wait(max_wait_timeout: 15.0)
|
329
|
+
|
330
|
+
consumer.subscribe(topic_name)
|
331
|
+
wait_for_assignment(consumer)
|
332
|
+
message = consumer.poll(100)
|
333
|
+
|
334
|
+
expect(message).to_not be_nil
|
335
|
+
|
336
|
+
consumer.commit
|
337
|
+
consumer.close
|
338
|
+
end
|
339
|
+
|
340
|
+
after do
|
341
|
+
producer.close
|
342
|
+
consumer.close
|
343
|
+
end
|
344
|
+
|
345
|
+
it "deletes the group" do
|
346
|
+
delete_group_handle = admin.delete_group(group_name)
|
347
|
+
report = delete_group_handle.wait(max_wait_timeout: 15.0)
|
348
|
+
|
349
|
+
expect(report.result_name).to eql(group_name)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
describe "called with invalid input" do
|
354
|
+
describe "with the name of a group that does not exist" do
|
355
|
+
it "raises an exception" do
|
356
|
+
delete_group_handle = admin.delete_group(group_name)
|
357
|
+
|
358
|
+
expect {
|
359
|
+
delete_group_handle.wait(max_wait_timeout: 15.0)
|
360
|
+
}.to raise_exception { |ex|
|
361
|
+
expect(ex).to be_a(Rdkafka::RdkafkaError)
|
362
|
+
expect(ex.message).to match(/Broker: The group id does not exist \(group_id_not_found\)/)
|
363
|
+
}
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
describe '#create_partitions' do
|
372
|
+
let(:metadata) { admin.metadata(topic_name).topics.first }
|
373
|
+
|
374
|
+
context 'when topic does not exist' do
|
375
|
+
it 'expect to fail due to unknown partition' do
|
376
|
+
expect { admin.create_partitions(topic_name, 10).wait }.to raise_error(Rdkafka::RdkafkaError, /unknown_topic_or_part/)
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
context 'when topic already has the desired number of partitions' do
|
381
|
+
before { admin.create_topic(topic_name, 2, 1).wait }
|
382
|
+
|
383
|
+
it 'expect not to change number of partitions' do
|
384
|
+
expect { admin.create_partitions(topic_name, 2).wait }.to raise_error(Rdkafka::RdkafkaError, /invalid_partitions/)
|
385
|
+
expect(metadata[:partition_count]).to eq(2)
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
context 'when topic has more than the requested number of partitions' do
|
390
|
+
before { admin.create_topic(topic_name, 5, 1).wait }
|
391
|
+
|
392
|
+
it 'expect not to change number of partitions' do
|
393
|
+
expect { admin.create_partitions(topic_name, 2).wait }.to raise_error(Rdkafka::RdkafkaError, /invalid_partitions/)
|
394
|
+
expect(metadata[:partition_count]).to eq(5)
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
context 'when topic has less then desired number of partitions' do
|
399
|
+
before { admin.create_topic(topic_name, 1, 1).wait }
|
400
|
+
|
401
|
+
it 'expect to change number of partitions' do
|
402
|
+
admin.create_partitions(topic_name, 10).wait
|
403
|
+
expect(metadata[:partition_count]).to eq(10)
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
203
407
|
end
|
data/spec/rdkafka/config_spec.rb
CHANGED
@@ -113,6 +113,14 @@ describe Rdkafka::Config do
|
|
113
113
|
consumer.close
|
114
114
|
end
|
115
115
|
|
116
|
+
it "should create a consumer with consumer_poll_set set to false" do
|
117
|
+
config = rdkafka_consumer_config
|
118
|
+
config.consumer_poll_set = false
|
119
|
+
consumer = config.consumer
|
120
|
+
expect(consumer).to be_a Rdkafka::Consumer
|
121
|
+
consumer.close
|
122
|
+
end
|
123
|
+
|
116
124
|
it "should raise an error when creating a consumer with invalid config" do
|
117
125
|
config = Rdkafka::Config.new('invalid.key' => 'value')
|
118
126
|
expect {
|
@@ -54,6 +54,30 @@ describe Rdkafka::Consumer do
|
|
54
54
|
consumer.subscription
|
55
55
|
}.to raise_error(Rdkafka::RdkafkaError)
|
56
56
|
end
|
57
|
+
|
58
|
+
context "when using consumer without the poll set" do
|
59
|
+
let(:consumer) do
|
60
|
+
config = rdkafka_consumer_config
|
61
|
+
config.consumer_poll_set = false
|
62
|
+
config.consumer
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should subscribe, unsubscribe and return the subscription" do
|
66
|
+
expect(consumer.subscription).to be_empty
|
67
|
+
|
68
|
+
consumer.subscribe("consume_test_topic")
|
69
|
+
|
70
|
+
expect(consumer.subscription).not_to be_empty
|
71
|
+
expected_subscription = Rdkafka::Consumer::TopicPartitionList.new.tap do |list|
|
72
|
+
list.add_topic("consume_test_topic")
|
73
|
+
end
|
74
|
+
expect(consumer.subscription).to eq expected_subscription
|
75
|
+
|
76
|
+
consumer.unsubscribe
|
77
|
+
|
78
|
+
expect(consumer.subscription).to be_empty
|
79
|
+
end
|
80
|
+
end
|
57
81
|
end
|
58
82
|
|
59
83
|
describe "#pause and #resume" do
|
@@ -273,6 +297,28 @@ describe Rdkafka::Consumer do
|
|
273
297
|
end
|
274
298
|
end
|
275
299
|
|
300
|
+
describe '#assignment_lost?' do
|
301
|
+
it "should not return true as we do have an assignment" do
|
302
|
+
consumer.subscribe("consume_test_topic")
|
303
|
+
expected_subscription = Rdkafka::Consumer::TopicPartitionList.new.tap do |list|
|
304
|
+
list.add_topic("consume_test_topic")
|
305
|
+
end
|
306
|
+
|
307
|
+
expect(consumer.assignment_lost?).to eq false
|
308
|
+
consumer.unsubscribe
|
309
|
+
end
|
310
|
+
|
311
|
+
it "should not return true after voluntary unsubscribing" do
|
312
|
+
consumer.subscribe("consume_test_topic")
|
313
|
+
expected_subscription = Rdkafka::Consumer::TopicPartitionList.new.tap do |list|
|
314
|
+
list.add_topic("consume_test_topic")
|
315
|
+
end
|
316
|
+
|
317
|
+
consumer.unsubscribe
|
318
|
+
expect(consumer.assignment_lost?).to eq false
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
276
322
|
describe "#close" do
|
277
323
|
it "should close a consumer" do
|
278
324
|
consumer.subscribe("consume_test_topic")
|
@@ -1054,6 +1100,29 @@ describe Rdkafka::Consumer do
|
|
1054
1100
|
end
|
1055
1101
|
end
|
1056
1102
|
|
1103
|
+
# Only relevant in case of a consumer with separate queues
|
1104
|
+
describe '#events_poll' do
|
1105
|
+
let(:stats) { [] }
|
1106
|
+
|
1107
|
+
before { Rdkafka::Config.statistics_callback = ->(published) { stats << published } }
|
1108
|
+
|
1109
|
+
after { Rdkafka::Config.statistics_callback = nil }
|
1110
|
+
|
1111
|
+
let(:consumer) do
|
1112
|
+
config = rdkafka_consumer_config('statistics.interval.ms': 100)
|
1113
|
+
config.consumer_poll_set = false
|
1114
|
+
config.consumer
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
it "expect to run events_poll, operate and propagate stats on events_poll and not poll" do
|
1118
|
+
consumer.subscribe("consume_test_topic")
|
1119
|
+
consumer.poll(1_000)
|
1120
|
+
expect(stats).to be_empty
|
1121
|
+
consumer.events_poll(-1)
|
1122
|
+
expect(stats).not_to be_empty
|
1123
|
+
end
|
1124
|
+
end
|
1125
|
+
|
1057
1126
|
describe "a rebalance listener" do
|
1058
1127
|
let(:consumer) do
|
1059
1128
|
config = rdkafka_consumer_config
|
data/spec/spec_helper.rb
CHANGED
@@ -11,6 +11,7 @@ require "pry"
|
|
11
11
|
require "rspec"
|
12
12
|
require "rdkafka"
|
13
13
|
require "timeout"
|
14
|
+
require "securerandom"
|
14
15
|
|
15
16
|
def rdkafka_base_config
|
16
17
|
{
|
@@ -35,7 +36,7 @@ def rdkafka_consumer_config(config_overrides={})
|
|
35
36
|
# Add consumer specific fields to it
|
36
37
|
config[:"auto.offset.reset"] = "earliest"
|
37
38
|
config[:"enable.partition.eof"] = false
|
38
|
-
config[:"group.id"] = "ruby-test-#{
|
39
|
+
config[:"group.id"] = "ruby-test-#{SecureRandom.uuid}"
|
39
40
|
# Enable debug mode if required
|
40
41
|
if ENV["DEBUG_CONSUMER"]
|
41
42
|
config[:debug] = "cgrp,topic,fetch"
|
@@ -134,6 +135,7 @@ RSpec.configure do |config|
|
|
134
135
|
rake_test_topic: 3,
|
135
136
|
watermarks_test_topic: 3,
|
136
137
|
partitioner_test_topic: 25,
|
138
|
+
example_topic: 1
|
137
139
|
}.each do |topic, partitions|
|
138
140
|
create_topic_handle = admin.create_topic(topic.to_s, partitions, 1)
|
139
141
|
begin
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rdkafka
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thijs Cadier
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
AnG1dJU+yL2BK7vaVytLTstJME5mepSZ46qqIJXMuWob/YPDmVaBF39TDSG9e34s
|
36
36
|
msG3BiCqgOgHAnL23+CN3Rt8MsuRfEtoTKpJVcCfoEoNHOkc
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date: 2023-
|
38
|
+
date: 2023-12-03 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: ffi
|
@@ -171,6 +171,7 @@ extensions:
|
|
171
171
|
- ext/Rakefile
|
172
172
|
extra_rdoc_files: []
|
173
173
|
files:
|
174
|
+
- ".github/FUNDING.yml"
|
174
175
|
- ".github/workflows/ci.yml"
|
175
176
|
- ".gitignore"
|
176
177
|
- ".rspec"
|
@@ -190,10 +191,21 @@ files:
|
|
190
191
|
- lib/rdkafka.rb
|
191
192
|
- lib/rdkafka/abstract_handle.rb
|
192
193
|
- lib/rdkafka/admin.rb
|
194
|
+
- lib/rdkafka/admin/acl_binding_result.rb
|
195
|
+
- lib/rdkafka/admin/create_acl_handle.rb
|
196
|
+
- lib/rdkafka/admin/create_acl_report.rb
|
197
|
+
- lib/rdkafka/admin/create_partitions_handle.rb
|
198
|
+
- lib/rdkafka/admin/create_partitions_report.rb
|
193
199
|
- lib/rdkafka/admin/create_topic_handle.rb
|
194
200
|
- lib/rdkafka/admin/create_topic_report.rb
|
201
|
+
- lib/rdkafka/admin/delete_acl_handle.rb
|
202
|
+
- lib/rdkafka/admin/delete_acl_report.rb
|
203
|
+
- lib/rdkafka/admin/delete_groups_handle.rb
|
204
|
+
- lib/rdkafka/admin/delete_groups_report.rb
|
195
205
|
- lib/rdkafka/admin/delete_topic_handle.rb
|
196
206
|
- lib/rdkafka/admin/delete_topic_report.rb
|
207
|
+
- lib/rdkafka/admin/describe_acl_handle.rb
|
208
|
+
- lib/rdkafka/admin/describe_acl_report.rb
|
197
209
|
- lib/rdkafka/bindings.rb
|
198
210
|
- lib/rdkafka/callbacks.rb
|
199
211
|
- lib/rdkafka/config.rb
|
@@ -213,10 +225,16 @@ files:
|
|
213
225
|
- rdkafka.gemspec
|
214
226
|
- renovate.json
|
215
227
|
- spec/rdkafka/abstract_handle_spec.rb
|
228
|
+
- spec/rdkafka/admin/create_acl_handle_spec.rb
|
229
|
+
- spec/rdkafka/admin/create_acl_report_spec.rb
|
216
230
|
- spec/rdkafka/admin/create_topic_handle_spec.rb
|
217
231
|
- spec/rdkafka/admin/create_topic_report_spec.rb
|
232
|
+
- spec/rdkafka/admin/delete_acl_handle_spec.rb
|
233
|
+
- spec/rdkafka/admin/delete_acl_report_spec.rb
|
218
234
|
- spec/rdkafka/admin/delete_topic_handle_spec.rb
|
219
235
|
- spec/rdkafka/admin/delete_topic_report_spec.rb
|
236
|
+
- spec/rdkafka/admin/describe_acl_handle_spec.rb
|
237
|
+
- spec/rdkafka/admin/describe_acl_report_spec.rb
|
220
238
|
- spec/rdkafka/admin_spec.rb
|
221
239
|
- spec/rdkafka/bindings_spec.rb
|
222
240
|
- spec/rdkafka/callbacks_spec.rb
|
@@ -267,10 +285,16 @@ summary: The rdkafka gem is a modern Kafka client library for Ruby based on libr
|
|
267
285
|
and Ruby 2.4+.
|
268
286
|
test_files:
|
269
287
|
- spec/rdkafka/abstract_handle_spec.rb
|
288
|
+
- spec/rdkafka/admin/create_acl_handle_spec.rb
|
289
|
+
- spec/rdkafka/admin/create_acl_report_spec.rb
|
270
290
|
- spec/rdkafka/admin/create_topic_handle_spec.rb
|
271
291
|
- spec/rdkafka/admin/create_topic_report_spec.rb
|
292
|
+
- spec/rdkafka/admin/delete_acl_handle_spec.rb
|
293
|
+
- spec/rdkafka/admin/delete_acl_report_spec.rb
|
272
294
|
- spec/rdkafka/admin/delete_topic_handle_spec.rb
|
273
295
|
- spec/rdkafka/admin/delete_topic_report_spec.rb
|
296
|
+
- spec/rdkafka/admin/describe_acl_handle_spec.rb
|
297
|
+
- spec/rdkafka/admin/describe_acl_report_spec.rb
|
274
298
|
- spec/rdkafka/admin_spec.rb
|
275
299
|
- spec/rdkafka/bindings_spec.rb
|
276
300
|
- spec/rdkafka/callbacks_spec.rb
|
metadata.gz.sig
CHANGED
Binary file
|