Skip to content

Commit 253b44d

Browse files
committed
fix: object_handling method for overriding defaults
Allows overriding values for newly created/replaced objects for mitigating issues on passing `None` value to sdk for params with default values. With this change pan-os-python does not need to accept 'none' value for the nexthop type in panos_static_route.
1 parent d067d91 commit 253b44d

File tree

3 files changed

+36
-16
lines changed

3 files changed

+36
-16
lines changed

plugins/module_utils/panos.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,20 @@ def spec_handling(self, spec, module):
555555
"""
556556
pass
557557

558+
def object_handling(self, obj, module):
559+
"""Override to provide custom functionality for newly created/replaced objects.
560+
561+
This method is run for newly created objects with merged state or
562+
created/replaced objects with present state.
563+
564+
By default it will handle default values for objects.
565+
It's advised to call `super().object_handling(obj, module)` if overriden
566+
in the modules.
567+
"""
568+
for key, obj_value in obj.about().items():
569+
if obj_value is None:
570+
setattr(obj, key, self._get_default_value(obj, key))
571+
558572
def pre_state_handling(self, obj, result, module):
559573
"""Override to provide custom pre-state handling functionality."""
560574
pass
@@ -694,6 +708,8 @@ def apply_state(
694708
continue
695709
other_children.append(x)
696710
item.remove(x)
711+
# object_handling need to be before equal comparison for evaluating defaults
712+
self.object_handling(obj, module)
697713
if not item.equal(obj, compare_children=True):
698714
result["changed"] = True
699715
obj.extend(other_children)
@@ -703,10 +719,6 @@ def apply_state(
703719
# NOTE checking defaults for with_update_in_apply_state doesnot have
704720
# a use for now as template, stack and device group dont have
705721
# defaults in the SDK
706-
# it also breaks panos_template as SDK has `mode` attribute set
707-
# to "normal" by default, but there is no xpath for this.
708-
# if obj_value is None:
709-
# setattr(obj, key, self._get_default_value(obj, key))
710722
if getattr(item, key) != getattr(obj, key):
711723
try:
712724
obj.update(key)
@@ -717,9 +729,6 @@ def apply_state(
717729
result["after"] = self.describe(obj)
718730
result["diff"]["after"] = eltostr(obj)
719731
else:
720-
for key, obj_value in obj.about().items():
721-
if obj_value is None:
722-
setattr(obj, key, self._get_default_value(obj, key))
723732
result["after"] = self.describe(obj)
724733
result["diff"]["after"] = eltostr(obj)
725734
try:
@@ -728,9 +737,7 @@ def apply_state(
728737
module.fail_json(msg="Failed apply: {0}".format(e))
729738
break
730739
else:
731-
for key, obj_value in obj.about().items():
732-
if obj_value is None:
733-
setattr(obj, key, self._get_default_value(obj, key))
740+
self.object_handling(obj, module)
734741
result["changed"] = True
735742
result["before"] = None
736743
result["after"] = self.describe(obj)
@@ -889,9 +896,7 @@ def apply_state(
889896
)
890897
break
891898
else: # create new record with merge
892-
for key, obj_value in obj.about().items():
893-
if obj_value is None:
894-
setattr(obj, key, self._get_default_value(obj, key))
899+
self.object_handling(obj, module)
895900
result["before"] = None
896901
result["after"] = self.describe(obj)
897902
result["diff"] = {

plugins/modules/panos_static_route.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,13 @@
5252
type: str
5353
nexthop_type:
5454
description:
55-
- Type of next hop.
55+
- Type of next hop. Defaults to I("ip-address").
5656
type: str
5757
choices:
5858
- ip-address
5959
- discard
6060
- none
6161
- next-vr
62-
default: 'ip-address'
6362
nexthop:
6463
description:
6564
- Next hop IP address. Required if I(state=present).
@@ -165,7 +164,11 @@ def spec_handling(self, spec, module):
165164
# default to ip-address when nexthop is set in merged state
166165
# we dont know if object exists or not in merged state, and we dont set default values in module invocation
167166
# in order to avoid unintended updates to non-provided params, but if nexthop is given, type must be ip-address
168-
if module.params["state"] == "merged" and spec["nexthop_type"] is None and spec["nexthop"] is not None:
167+
if (
168+
module.params["state"] == "merged"
169+
and spec["nexthop_type"] is None
170+
and spec["nexthop"] is not None
171+
):
169172
spec["nexthop_type"] = "ip-address"
170173

171174
# NOTE merged state have a lot of API issues for updating nexthop we will let the API return it..
@@ -181,6 +184,10 @@ def spec_handling(self, spec, module):
181184
]
182185
module.fail_json(msg=" ".join(msg))
183186

187+
def object_handling(self, obj, module):
188+
super().object_handling(obj, module)
189+
if module.params.get("nexthop_type") == "none":
190+
setattr(obj, "nexthop_type", None)
184191

185192

186193
def main():

plugins/modules/panos_template.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,14 @@ def pre_state_handling(self, obj, result, module):
105105
vsys = to_sdk_cls("device", "Vsys")(module.params["default_vsys"])
106106
obj.add(vsys)
107107

108+
def object_handling(self, obj, module):
109+
super().object_handling(obj, module)
110+
# override 'mode' param sdk default to None if it's not set explicitly in invocation.
111+
# SDK has `mode` attribute set to "normal" by default, but there is no xpath for this
112+
# resulting in xpath schema error if default is used.
113+
if module.params.get("mode") is None:
114+
setattr(obj, "mode", None)
115+
108116

109117
def main():
110118
helper = get_connection(

0 commit comments

Comments
 (0)