Fix infinite recursion on action module import

Ansible imports our module with the name ansible.plugins.action.normal
(regardless of its actual path).  This line would then import the original
module, also under the same name, so it would overwrite ours.  Correct
this by importing the original with a unique name.  It's not actually
used anywhere anyway.

Change-Id: I5dd26e2f89399f991cebc23839a36e7aff47056c
diff --git a/zuul/ansible/action/normal.py b/zuul/ansible/action/normal.py
index a50125c..b18cb51 100644
--- a/zuul/ansible/action/normal.py
+++ b/zuul/ansible/action/normal.py
@@ -13,12 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this software.  If not, see <http://www.gnu.org/licenses/>.
 
-# TODO(mordred) Figure out how to not need to do this to get the base class
-import ansible.plugins.action
-import imp
-normal = imp.load_module(
-    'ansible.plugins.action.normal',
-    *imp.find_module('normal', ansible.plugins.action.__path__))
+from zuul.ansible import paths
+normal = paths._import_ansible_action_plugin('normal')
 
 
 class ActionModule(normal.ActionModule):
diff --git a/zuul/ansible/paths.py b/zuul/ansible/paths.py
index 2bd0181..cde43f1 100644
--- a/zuul/ansible/paths.py
+++ b/zuul/ansible/paths.py
@@ -13,8 +13,11 @@
 # You should have received a copy of the GNU General Public License
 # along with this software.  If not, see <http://www.gnu.org/licenses/>.
 
+import imp
 import os
 
+import ansible.plugins.action
+
 
 def _is_safe_path(path):
     if os.path.isabs(path):
@@ -31,3 +34,21 @@
         path=path,
         msg="{prefix} outside the working dir is prohibited".format(
             prefix=prefix))
+
+
+def _import_ansible_action_plugin(name):
+    # Ansible forces the import of our action plugins
+    # (zuul.ansible.action.foo) as ansible.plugins.action.foo, which
+    # is the import path of the ansible implementation.  Our
+    # implementations need to subclass that, but if we try to import
+    # it with that name, we will get our own module.  This bypasses
+    # Python's module namespace to load the actual ansible modules.
+    # We need to give it a name, however.  If we load it with its
+    # actual name, we will end up overwriting our module in Python's
+    # namespace, causing infinite recursion.  So we supply an
+    # otherwise unused name for the module:
+    # zuul.ansible.protected.action.foo.
+
+    return imp.load_module(
+        'zuul.ansible.protected.action.' + name,
+        *imp.find_module(name, ansible.plugins.action.__path__))