diff --git a/dim-testsuite/t/pool-delete-dryrun.t b/dim-testsuite/t/pool-delete-dryrun.t new file mode 100644 index 0000000..b67d439 --- /dev/null +++ b/dim-testsuite/t/pool-delete-dryrun.t @@ -0,0 +1,26 @@ +# ITOUDP-6303: with -n ndcli sends dryrun to every call, also to read-only +# ones like ippool_get_subnets, which used to fail with +# "unexpected keyword argument 'dryrun'". +$ ndcli create container 10.0.0.0/8 layer3domain default +INFO - Creating container 10.0.0.0/8 in layer3domain default +$ ndcli create pool p layer3domain default + +$ ndcli delete pool p -f -n +INFO - Dryrun mode, no data will be modified + +# nothing was deleted +$ ndcli list pools p +INFO - Result for list pools p +name vlan subnets layer3domain +p default + +$ ndcli modify pool p add subnet 10.0.0.0/24 +INFO - Created subnet 10.0.0.0/24 in layer3domain default +WARNING - Creating zone 0.0.10.in-addr.arpa without profile +WARNING - Primary NS for this Domain is now localhost. +$ ndcli delete pool p -n +INFO - Dryrun mode, no data will be modified +ERROR - You cannot delete pool because it contains 1 subnet(s). However, you can use --force option to delete it. + +$ ndcli delete pool p +ERROR - You cannot delete pool because it contains 1 subnet(s). However, you can use --force option to delete it. diff --git a/dim/CHANGES b/dim/CHANGES index 0bb36d3..4a4841a 100644 --- a/dim/CHANGES +++ b/dim/CHANGES @@ -1,5 +1,6 @@ to be released ------ +* read-only calls ignore `dryrun`, so `ndcli -n` no longer fails with "unexpected keyword argument 'dryrun'" (ITOUDP-6303) * added ldap pseudo user sync to manage_dim (introduces is_pseudo column, LDAP_PSEUDO_USER_BASE, LDAP_BIND_DN, and LDAP_BIND_PASSWORD configurations) * added automated database schema mismatch verification check on application startup * reject attribute names containing colons during deletion to prevent silent failure from incorrect key-value input diff --git a/dim/dim/transaction.py b/dim/dim/transaction.py index 1ecf3d9..95d8014 100644 --- a/dim/dim/transaction.py +++ b/dim/dim/transaction.py @@ -139,6 +139,17 @@ def transaction_delayed_lock(f): return retryable_transaction(_transaction_delayed_lock(f)) +def _ignore_dryrun(f): + '''A read-only call has nothing to roll back, so dryrun does not apply to it. + + ndcli -n sends dryrun with every call, read-only ones included.''' + @wraps(f) + def wrapper(*args, **kwargs): + kwargs.pop('dryrun', None) + return f(*args, **kwargs) + return wrapper + + class TransactionProxy(object): def __init__(self, obj): self.obj = obj @@ -148,7 +159,7 @@ def __getattr__(self, name): func = getattr(self.obj, name) if callable(func): if getattr(func, 'readonly', False): - return user_session(self.obj.username, self.obj.tool, self.obj.ip)(time_function(func)) + return user_session(self.obj.username, self.obj.tool, self.obj.ip)(time_function(_ignore_dryrun(func))) elif getattr(func, 'delayed_lock', False): return user_session(self.obj.username, self.obj.tool, self.obj.ip)( time_function(transaction_delayed_lock(func)))