Description
PolicySetControllerAPI.update_isolation_rule and update_isolation_rule_v2 both declare
action: str = None, but build their payload with an unguarded action.upper()
(zscaler/zpa/policies.py:1308 and :2523 on master e7f5f7e). Omitting action — as you
would for a partial update — raises before any request is made, so those two methods cannot do
a partial update at all.
Sibling update methods in the same file already guard this, e.g. update_access_rule
(policies.py:695) uses "action": action.upper() if action else None, so this looks like an
oversight rather than intent.
Reproduction
No credentials needed — the request executor is mocked, so the failure happens while building
the payload:
from unittest.mock import Mock
from zscaler.zpa.policies import PolicySetControllerAPI
policy_set = Mock()
policy_set.get_body.return_value = {"id": "72058304855090130"}
executor = Mock()
executor.create_request.return_value = ({}, None)
executor.execute.side_effect = [(policy_set, None), (None, None)]
api = PolicySetControllerAPI(executor, {"client": {"customerId": "72058304855090128"}})
# Partial update: change only the description, leave action untouched.
api.update_isolation_rule_v2(rule_id="72058304855090129", description="partial update")
The equivalent real call is
client.zpa.policies.update_isolation_rule_v2(rule_id="72058304855090129", description="partial update").
update_isolation_rule (v1) fails the same way.
Expected behavior
The update request is sent with the fields that were supplied, the same as
update_access_rule_v2 / update_client_forwarding_rule_v2 already do when action is omitted.
Actual behavior
File ".../zscaler/zpa/policies.py", line 2523, in update_isolation_rule_v2
"action": action.upper(),
^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'upper'
Other Information
- SDK version: 1.9.44 (master
e7f5f7e)
- Python 3.12
- A PR is attached: it applies the existing
action.upper() if action else None guard to both
sites and adds a unit test covering the partial-update path.
Description
PolicySetControllerAPI.update_isolation_ruleandupdate_isolation_rule_v2both declareaction: str = None, but build their payload with an unguardedaction.upper()(
zscaler/zpa/policies.py:1308and:2523on mastere7f5f7e). Omittingaction— as youwould for a partial update — raises before any request is made, so those two methods cannot do
a partial update at all.
Sibling update methods in the same file already guard this, e.g.
update_access_rule(
policies.py:695) uses"action": action.upper() if action else None, so this looks like anoversight rather than intent.
Reproduction
No credentials needed — the request executor is mocked, so the failure happens while building
the payload:
The equivalent real call is
client.zpa.policies.update_isolation_rule_v2(rule_id="72058304855090129", description="partial update").update_isolation_rule(v1) fails the same way.Expected behavior
The update request is sent with the fields that were supplied, the same as
update_access_rule_v2/update_client_forwarding_rule_v2already do whenactionis omitted.Actual behavior
Other Information
e7f5f7e)action.upper() if action else Noneguard to bothsites and adds a unit test covering the partial-update path.