issue #217: pass through non-custom module utils to regular importer.
This may come back to bite later, but in the meantime it avoids shipping up to 12KiB of junk metadata for every single task invocation. For detachment (aka. async), we must ensure the target has two types of preloads completed (modules and module_utils files) before detaching.
This commit is contained in:
parent
30034877a5
commit
bb61745a1a
|
@ -1,12 +1,37 @@
|
|||
# Copyright 2017, David Wilson
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from __future__ import absolute_import
|
||||
import collections
|
||||
import imp
|
||||
import os
|
||||
import sys
|
||||
|
||||
import mitogen.master
|
||||
import ansible.module_utils
|
||||
|
||||
|
||||
PREFIX = 'ansible.module_utils.'
|
||||
|
@ -16,6 +41,9 @@ Module = collections.namedtuple('Module', 'name path kind parent')
|
|||
|
||||
|
||||
def get_fullname(module):
|
||||
"""
|
||||
Reconstruct a Module's canonical path by recursing through its parents.
|
||||
"""
|
||||
bits = [str(module.name)]
|
||||
while module.parent:
|
||||
bits.append(str(module.parent.name))
|
||||
|
@ -24,6 +52,9 @@ def get_fullname(module):
|
|||
|
||||
|
||||
def get_code(module):
|
||||
"""
|
||||
Compile and return a Module's code object.
|
||||
"""
|
||||
fp = open(module.path)
|
||||
try:
|
||||
return compile(fp.read(), str(module.name), 'exec')
|
||||
|
@ -32,12 +63,23 @@ def get_code(module):
|
|||
|
||||
|
||||
def is_pkg(module):
|
||||
"""
|
||||
Return :data:`True` if a Module represents a package.
|
||||
"""
|
||||
return module.kind == imp.PKG_DIRECTORY
|
||||
|
||||
|
||||
def find(name, path=(), parent=None):
|
||||
"""
|
||||
(Name, search path) -> Module instance or None.
|
||||
Return a Module instance describing the first matching module found on the
|
||||
given search path.
|
||||
|
||||
:param str name:
|
||||
Module name.
|
||||
:param str path:
|
||||
Search path.
|
||||
:param Module parent:
|
||||
If given, make the found module a child of this module.
|
||||
"""
|
||||
head, _, tail = name.partition('.')
|
||||
try:
|
||||
|
@ -71,12 +113,7 @@ def scan_fromlist(code):
|
|||
|
||||
|
||||
def scan(module_name, module_path, search_path):
|
||||
module = Module(
|
||||
name=module_name,
|
||||
path=module_path,
|
||||
kind=imp.PY_SOURCE,
|
||||
parent=None,
|
||||
)
|
||||
module = Module(module_name, module_path, imp.PY_SOURCE, None)
|
||||
stack = [module]
|
||||
seen = set()
|
||||
|
||||
|
@ -90,19 +127,12 @@ def scan(module_name, module_path, search_path):
|
|||
if imported is None or imported in seen:
|
||||
continue
|
||||
|
||||
if imported in seen:
|
||||
continue
|
||||
|
||||
seen.add(imported)
|
||||
stack.append(imported)
|
||||
parent = imported.parent
|
||||
while parent:
|
||||
module = Module(
|
||||
name=get_fullname(parent),
|
||||
path=parent.path,
|
||||
kind=parent.kind,
|
||||
parent=None,
|
||||
)
|
||||
fullname = get_fullname(parent)
|
||||
module = Module(fullname, parent.path, parent.kind, None)
|
||||
if module not in seen:
|
||||
seen.add(module)
|
||||
stack.append(module)
|
||||
|
|
|
@ -292,38 +292,33 @@ class NewStylePlanner(ScriptPlanner):
|
|||
def detect(self, invocation):
|
||||
return 'from ansible.module_utils.' in invocation.module_source
|
||||
|
||||
def get_module_utils_path(self, invocation):
|
||||
paths = [
|
||||
def get_search_path(self, invocation):
|
||||
return tuple(
|
||||
path
|
||||
for path in module_utils_loader._get_paths(subdirs=False)
|
||||
if os.path.isdir(path)
|
||||
]
|
||||
paths.append(module_common._MODULE_UTILS_PATH)
|
||||
return tuple(paths)
|
||||
)
|
||||
|
||||
def get_module_utils(self, invocation):
|
||||
invocation.connection._connect()
|
||||
module_utils = mitogen.service.call(
|
||||
return mitogen.service.call(
|
||||
context=invocation.connection.parent,
|
||||
handle=ansible_mitogen.services.ModuleDepService.handle,
|
||||
method='scan',
|
||||
kwargs={
|
||||
'module_name': 'ansible_module_%s' % (invocation.module_name,),
|
||||
'module_path': invocation.module_path,
|
||||
'search_path': self.get_module_utils_path(invocation),
|
||||
'search_path': self.get_search_path(invocation),
|
||||
'builtin_path': module_common._MODULE_UTILS_PATH,
|
||||
}
|
||||
)
|
||||
modutils_dir = os.path.dirname(ansible.module_utils.__file__)
|
||||
has_custom = not all(path.startswith(modutils_dir)
|
||||
for fullname, path, is_pkg in module_utils)
|
||||
return module_utils, has_custom
|
||||
|
||||
def plan(self, invocation):
|
||||
module_utils, has_custom = self.get_module_utils(invocation)
|
||||
module_utils = self.get_module_utils(invocation)
|
||||
return super(NewStylePlanner, self).plan(
|
||||
invocation,
|
||||
module_utils=module_utils,
|
||||
should_fork=(self.get_should_fork(invocation) or has_custom),
|
||||
should_fork=(self.get_should_fork(invocation) or bool(module_utils)),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -622,20 +622,27 @@ class ModuleDepService(mitogen.service.Service):
|
|||
'module_name': basestring,
|
||||
'module_path': basestring,
|
||||
'search_path': tuple,
|
||||
'builtin_path': basestring,
|
||||
})
|
||||
def scan(self, module_name, module_path, search_path):
|
||||
def scan(self, module_name, module_path, search_path, builtin_path):
|
||||
if (module_name, search_path) not in self._cache:
|
||||
resolved = ansible_mitogen.module_finder.scan(
|
||||
module_name=module_name,
|
||||
module_path=module_path,
|
||||
search_path=search_path,
|
||||
search_path=tuple(search_path) + (builtin_path,),
|
||||
)
|
||||
self._cache[module_name, search_path] = resolved
|
||||
builtin_path = os.path.abspath(builtin_path)
|
||||
filtered = [
|
||||
(fullname, path, is_pkg)
|
||||
for fullname, path, is_pkg in resolved
|
||||
if not os.path.abspath(path).startswith(builtin_path)
|
||||
]
|
||||
self._cache[module_name, search_path] = filtered
|
||||
|
||||
# Grant FileService access to paths in here to avoid another 2 IPCs
|
||||
# from WorkerProcess.
|
||||
self._file_service.register(path=module_path)
|
||||
for fullname, path, is_pkg in resolved:
|
||||
for fullname, path, is_pkg in filtered:
|
||||
self._file_service.register(path=path)
|
||||
|
||||
return self._cache[module_name, search_path]
|
||||
|
|
|
@ -518,7 +518,7 @@ def write_path(path, s, owner=None, group=None, mode=None,
|
|||
prefix='.ansible_mitogen_transfer-',
|
||||
dir=os.path.dirname(path))
|
||||
fp = os.fdopen(fd, 'wb', mitogen.core.CHUNK_SIZE)
|
||||
LOG.debug('write_path(path=%r) tempory file: %s', path, tmp_path)
|
||||
LOG.debug('write_path(path=%r) temporary file: %s', path, tmp_path)
|
||||
|
||||
try:
|
||||
try:
|
||||
|
|
Loading…
Reference in New Issue