Repository: rucio/rucio

Issue:
Allow reason in ruleclient when denying a rule
### Description

Currently [ruleclient.py](https://github.com/rucio/rucio/blob/98b18092263e2fe9dddffc30798a94d7a04a075b/lib/rucio/client/ruleclient.py) does not allow to give a reason in `deny_replication_rule()`.

The basic functionality was implemented in #487, though, and is also available in the web interface.

It would be useful if the ruleclient could use this functionality.

### Motivation

Currently, when using the rule client to deny rules, the users will simply get `Reason: None`. If operators want to give a reason, they either need to write a mail manually or use the web interface. The latter is not really an option if you want to "bulk-deny" tens or hundreds of rules. Simply bulk-denying with, e.g., `Reason: No lifetime set` would be great.

### Change

From looking at #487, it should be sufficient to add a new parameter to the function below and in the options to the web request add `'comment': reason`.
https://github.com/rucio/rucio/blob/98b18092263e2fe9dddffc30798a94d7a04a075b/lib/rucio/client/ruleclient.py#L180-L193

If you think this would be a reasonable change, I would be happy to try and implement it. (Although I need to figure out a reasonable test setup/scenario.)
Allow reason in ruleclient when denying a rule
### Description

Currently [ruleclient.py](https://github.com/rucio/rucio/blob/98b18092263e2fe9dddffc30798a94d7a04a075b/lib/rucio/client/ruleclient.py) does not allow to give a reason in `deny_replication_rule()`.

The basic functionality was implemented in #487, though, and is also available in the web interface.

It would be useful if the ruleclient could use this functionality.

### Motivation

Currently, when using the rule client to deny rules, the users will simply get `Reason: None`. If operators want to give a reason, they either need to write a mail manually or use the web interface. The latter is not really an option if you want to "bulk-deny" tens or hundreds of rules. Simply bulk-denying with, e.g., `Reason: No lifetime set` would be great.

### Change

From looking at #487, it should be sufficient to add a new parameter to the function below and in the options to the web request add `'comment': reason`.
https://github.com/rucio/rucio/blob/98b18092263e2fe9dddffc30798a94d7a04a075b/lib/rucio/client/ruleclient.py#L180-L193

If you think this would be a reasonable change, I would be happy to try and implement it. (Although I need to figure out a reasonable test setup/scenario.)


Discussion:

Resolving patch:
diff --git a/lib/rucio/client/ruleclient.py b/lib/rucio/client/ruleclient.py
--- a/lib/rucio/client/ruleclient.py
+++ b/lib/rucio/client/ruleclient.py
@@ -203,15 +203,19 @@ def approve_replication_rule(self, rule_id: str):
         exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content)
         raise exc_cls(exc_msg)
 
-    def deny_replication_rule(self, rule_id: str):
+    def deny_replication_rule(self, rule_id: str, reason: Optional[str] = None):
         """
         :param rule_id:             Rule to be denied.
+        :param reason:              Reason for denying the rule.
         :raises:                    RuleNotFound
         """
 
         path = self.RULE_BASEURL + '/' + rule_id
         url = build_url(choice(self.list_hosts), path=path)
-        data = dumps({'options': {'approve': False}})
+        options: Dict[str, Union[bool, str]] = {'approve': False}
+        if reason:
+            options['comment'] = reason
+        data = dumps({'options': options})
         r = self._send_request(url, type_='PUT', data=data)
         if r.status_code == codes.ok:
             return True


Test patch: