From 854d47826cec7c557fa79a6484f9a6aa240a6ed6 Mon Sep 17 00:00:00 2001 From: Toshio Kuratomi Date: Thu, 11 Aug 2016 10:26:17 -0700 Subject: [PATCH] Fix classes that select a subclass based on platform (#17034) When unittesting this we found that the platform selecting class hierarchies weren't working in all cases. If the subclass was directly created (ie: LinuxHardware()), then it would use its inherited __new__() to try to create itself. The inherited __new__ would look for subclasses and end up calling its own __new__() again. This would recurse endlessly. The new code detects when we want to find a subclass to create (when the base class is used, ie: Hardware()) vs when to create the class itself (when the subclass is used, ie: LinuxHardware()). --- lib/ansible/module_utils/facts.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/ansible/module_utils/facts.py b/lib/ansible/module_utils/facts.py index c43723d0791..b02c821ee92 100644 --- a/lib/ansible/module_utils/facts.py +++ b/lib/ansible/module_utils/facts.py @@ -961,6 +961,12 @@ class Hardware(Facts): platform = 'Generic' def __new__(cls, *arguments, **keyword): + # When Hardware is created, it chooses a subclass to create instead. + # This check prevents the subclass from then trying to find a subclass + # and create that. + if cls is not Hardware: + return super(Hardware, cls).__new__(cls) + subclass = cls for sc in get_all_subclasses(Hardware): if sc.platform == platform.system(): @@ -2052,6 +2058,12 @@ class Network(Facts): '80' : 'organization' } def __new__(cls, *arguments, **keyword): + # When Network is created, it chooses a subclass to create instead. + # This check prevents the subclass from then trying to find a subclass + # and create that. + if cls is not Network: + return super(Network, cls).__new__(cls) + subclass = cls for sc in get_all_subclasses(Network): if sc.platform == platform.system(): @@ -2836,6 +2848,12 @@ class Virtual(Facts): """ def __new__(cls, *arguments, **keyword): + # When Virtual is created, it chooses a subclass to create instead. + # This check prevents the subclass from then trying to find a subclass + # and create that. + if cls is not Virtual: + return super(Virtual, cls).__new__(cls) + subclass = cls for sc in get_all_subclasses(Virtual): if sc.platform == platform.system():