Skip to content

Commit b304ed0

Browse files
authored
Fix for duplicate acls (confluentinc#1370)
raised ValueError if duplicate ACL bindings or ACL binding filters are passed.
1 parent ebd8459 commit b304ed0

File tree

4 files changed

+34
-12
lines changed

4 files changed

+34
-12
lines changed

docs/index.rst

+6-6
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ ResourceType
136136

137137
.. _pythonclient_resource_pattern_type:
138138

139-
**************
139+
*******************
140140
ResourcePatternType
141-
**************
141+
*******************
142142

143143
.. autoclass:: confluent_kafka.admin.ResourcePatternType
144144
:members:
@@ -154,9 +154,9 @@ AclOperation
154154

155155
.. _pythonclient_acl_permission_type:
156156

157-
**************
157+
*****************
158158
AclPermissionType
159-
**************
159+
*****************
160160

161161
.. autoclass:: confluent_kafka.admin.AclPermissionType
162162
:members:
@@ -172,9 +172,9 @@ AclBinding
172172

173173
.. _pythonclient_acl_binding_filter:
174174

175-
**************
175+
****************
176176
AclBindingFilter
177-
**************
177+
****************
178178

179179
.. autoclass:: confluent_kafka.admin.AclBindingFilter
180180
:members:

examples/adminapi.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,11 @@ def example_create_acls(a, args):
152152
)
153153
]
154154

155-
fs = a.create_acls(acl_bindings, request_timeout=10)
155+
try:
156+
fs = a.create_acls(acl_bindings, request_timeout=10)
157+
except ValueError as e:
158+
print(f"create_acls() failed: {e}")
159+
return
156160

157161
# Wait for operation to finish.
158162
for res, f in fs.items():
@@ -237,7 +241,11 @@ def example_delete_acls(a, args):
237241
)
238242
]
239243

240-
fs = a.delete_acls(acl_binding_filters, request_timeout=10)
244+
try:
245+
fs = a.delete_acls(acl_binding_filters, request_timeout=10)
246+
except ValueError as e:
247+
print(f"delete_acls() failed: {e}")
248+
return
241249

242250
# Wait for operation to finish.
243251
for res, f in fs.items():

src/confluent_kafka/admin/__init__.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ def _make_futures(futmap_keys, class_check, make_result_fn):
181181

182182
return f, futmap
183183

184+
@staticmethod
185+
def _has_duplicates(items):
186+
return len(set(items)) != len(items)
187+
184188
def create_topics(self, new_topics, **kwargs):
185189
"""
186190
Create one or more new topics.
@@ -365,7 +369,7 @@ def create_acls(self, acls, **kwargs):
365369
"""
366370
Create one or more ACL bindings.
367371
368-
:param list(AclBinding) acls: A list of ACL binding specifications (:class:`.AclBinding`)
372+
:param list(AclBinding) acls: A list of unique ACL binding specifications (:class:`.AclBinding`)
369373
to create.
370374
:param float request_timeout: The overall request timeout in seconds,
371375
including broker lookup, request transmission, operation time
@@ -380,6 +384,8 @@ def create_acls(self, acls, **kwargs):
380384
:raises TypeException: Invalid input.
381385
:raises ValueException: Invalid input.
382386
"""
387+
if AdminClient._has_duplicates(acls):
388+
raise ValueError("duplicate ACL bindings not allowed")
383389

384390
f, futmap = AdminClient._make_futures(acls, AclBinding,
385391
AdminClient._make_acls_result)
@@ -395,7 +401,7 @@ def describe_acls(self, acl_binding_filter, **kwargs):
395401
:param AclBindingFilter acl_binding_filter: a filter with attributes that
396402
must match.
397403
String attributes match exact values or any string if set to None.
398-
Enums attributes match exact values or any value if ending with `_ANY`.
404+
Enums attributes match exact values or any value if equal to `ANY`.
399405
If :class:`ResourcePatternType` is set to :attr:`ResourcePatternType.MATCH` returns all
400406
the ACL bindings with :attr:`ResourcePatternType.LITERAL`,
401407
:attr:`ResourcePatternType.WILDCARD` or :attr:`ResourcePatternType.PREFIXED` pattern
@@ -423,10 +429,10 @@ def delete_acls(self, acl_binding_filters, **kwargs):
423429
"""
424430
Delete ACL bindings matching one or more ACL binding filters.
425431
426-
:param list(AclBindingFilter) acl_binding_filters: a list of ACL binding filters
432+
:param list(AclBindingFilter) acl_binding_filters: a list of unique ACL binding filters
427433
to match ACLs to delete.
428434
String attributes match exact values or any string if set to None.
429-
Enums attributes match exact values or any value if ending with `_ANY`.
435+
Enums attributes match exact values or any value if equal to `ANY`.
430436
If :class:`ResourcePatternType` is set to :attr:`ResourcePatternType.MATCH`
431437
deletes all the ACL bindings with :attr:`ResourcePatternType.LITERAL`,
432438
:attr:`ResourcePatternType.WILDCARD` or :attr:`ResourcePatternType.PREFIXED`
@@ -444,6 +450,8 @@ def delete_acls(self, acl_binding_filters, **kwargs):
444450
:raises TypeException: Invalid input.
445451
:raises ValueException: Invalid input.
446452
"""
453+
if AdminClient._has_duplicates(acl_binding_filters):
454+
raise ValueError("duplicate ACL binding filters not allowed")
447455

448456
f, futmap = AdminClient._make_futures(acl_binding_filters, AclBindingFilter,
449457
AdminClient._make_acls_result)

tests/test_Admin.py

+6
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,9 @@ def test_create_acls_api():
347347
with pytest.raises(ValueError):
348348
a.create_acls([None, acl_binding1])
349349

350+
with pytest.raises(ValueError):
351+
a.create_acls([acl_binding1, acl_binding1])
352+
350353
fs = a.create_acls([acl_binding1, acl_binding2])
351354
with pytest.raises(KafkaException):
352355
for f in fs.values():
@@ -391,6 +394,9 @@ def test_delete_acls_api():
391394
with pytest.raises(ValueError):
392395
a.delete_acls([None, acl_binding_filter1])
393396

397+
with pytest.raises(ValueError):
398+
a.delete_acls([acl_binding_filter1, acl_binding_filter1])
399+
394400
fs = a.delete_acls([acl_binding_filter1, acl_binding_filter2])
395401
with pytest.raises(KafkaException):
396402
for f in concurrent.futures.as_completed(iter(fs.values())):

0 commit comments

Comments
 (0)