Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: object_handling method for overriding defaults #589

Merged
merged 2 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 18 additions & 13 deletions plugins/module_utils/panos.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,20 @@ def spec_handling(self, spec, module):
"""
pass

def object_handling(self, obj, module):
"""Override to provide custom functionality for newly created/replaced objects.

This method is run for newly created objects with merged state or
created/replaced objects with present state.

By default it will handle default values for objects.
It's advised to call `super().object_handling(obj, module)` if overriden
in the modules.
"""
for key, obj_value in obj.about().items():
if obj_value is None:
setattr(obj, key, self._get_default_value(obj, key))

def pre_state_handling(self, obj, result, module):
"""Override to provide custom pre-state handling functionality."""
pass
Expand Down Expand Up @@ -694,6 +708,8 @@ def apply_state(
continue
other_children.append(x)
item.remove(x)
# object_handling need to be before equal comparison for evaluating defaults
self.object_handling(obj, module)
if not item.equal(obj, compare_children=True):
result["changed"] = True
obj.extend(other_children)
Expand All @@ -703,10 +719,6 @@ def apply_state(
# NOTE checking defaults for with_update_in_apply_state doesnot have
# a use for now as template, stack and device group dont have
# defaults in the SDK
# it also breaks panos_template as SDK has `mode` attribute set
# to "normal" by default, but there is no xpath for this.
# if obj_value is None:
# setattr(obj, key, self._get_default_value(obj, key))
if getattr(item, key) != getattr(obj, key):
try:
obj.update(key)
Expand All @@ -717,9 +729,6 @@ def apply_state(
result["after"] = self.describe(obj)
result["diff"]["after"] = eltostr(obj)
else:
for key, obj_value in obj.about().items():
if obj_value is None:
setattr(obj, key, self._get_default_value(obj, key))
result["after"] = self.describe(obj)
result["diff"]["after"] = eltostr(obj)
try:
Expand All @@ -728,9 +737,7 @@ def apply_state(
module.fail_json(msg="Failed apply: {0}".format(e))
break
else:
for key, obj_value in obj.about().items():
if obj_value is None:
setattr(obj, key, self._get_default_value(obj, key))
self.object_handling(obj, module)
result["changed"] = True
result["before"] = None
result["after"] = self.describe(obj)
Expand Down Expand Up @@ -889,9 +896,7 @@ def apply_state(
)
break
else: # create new record with merge
for key, obj_value in obj.about().items():
if obj_value is None:
setattr(obj, key, self._get_default_value(obj, key))
self.object_handling(obj, module)
result["before"] = None
result["after"] = self.describe(obj)
result["diff"] = {
Expand Down
34 changes: 29 additions & 5 deletions plugins/modules/panos_static_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,13 @@
type: str
nexthop_type:
description:
- Type of next hop.
- Type of next hop. Defaults to I("ip-address").
type: str
choices:
- ip-address
- discard
- none
- next-vr
default: 'ip-address'
nexthop:
description:
- Next hop IP address. Required if I(state=present).
Expand Down Expand Up @@ -157,15 +156,38 @@

class Helper(ConnectionHelper):
def spec_handling(self, spec, module):
if module.params["state"] == "present" and spec["nexthop_type"] is None:
# need this because we dont have the default assignment in sdk-params and
# `None` value params are being removed in ParamPath.element method (called via VersionedPanObject.element)
spec["nexthop_type"] = "ip-address"

# default to ip-address when nexthop is set in merged state
# we dont know if object exists or not in merged state, and we dont set default values in module invocation
# in order to avoid unintended updates to non-provided params, but if nexthop is given, type must be ip-address
if (
module.params["state"] == "merged"
and spec["nexthop_type"] is None
and spec["nexthop"] is not None
):
spec["nexthop_type"] = "ip-address"
adambaumeister marked this conversation as resolved.
Show resolved Hide resolved

# NOTE merged state have a lot of API issues for updating nexthop we will let the API return it..
# from None to IP address - "Failed update nexthop_type: Edit breaks config validity"
# from IP address to next-vr - "Failed update nexthop_type: Edit breaks config validity"

# applies for updating existing routes from IP/next-vr/discard to none
# however it works for new objects, we ignore this as this is the existing implementation
if module.params["state"] == "merged" and spec["nexthop_type"] == "none":
msg = [
"Nexthop cannot be set to None with state='merged'.",
"You will need to use either state='present' or state='replaced'.",
]
module.fail_json(msg=" ".join(msg))

if spec["nexthop_type"] == "none":
spec["nexthop_type"] = None
def object_handling(self, obj, module):
super().object_handling(obj, module)
if module.params.get("nexthop_type") == "none":
setattr(obj, "nexthop_type", None)


def main():
Expand All @@ -182,7 +204,6 @@ def main():
name=dict(required=True),
destination=dict(),
nexthop_type=dict(
default="ip-address",
choices=["ip-address", "discard", "none", "next-vr"],
),
nexthop=dict(),
Expand All @@ -193,6 +214,9 @@ def main():
failure_condition=dict(choices=["any", "all"]),
preemptive_hold_time=dict(type="int"),
),
default_values=dict(
nexthop_type="ip-address",
),
)

module = AnsibleModule(
Expand Down
8 changes: 8 additions & 0 deletions plugins/modules/panos_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ def pre_state_handling(self, obj, result, module):
vsys = to_sdk_cls("device", "Vsys")(module.params["default_vsys"])
obj.add(vsys)

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


def main():
helper = get_connection(
Expand Down
Loading