|
|
|
@ -27,6 +27,7 @@ from .util import (
|
|
|
|
|
|
|
|
|
|
from .data import (
|
|
|
|
|
data_context,
|
|
|
|
|
PayloadConfig,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
from .util_common import (
|
|
|
|
@ -44,11 +45,66 @@ def create_payload(args: CommonConfig, dst_path: str) -> None:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
files = list(data_context().ansible_source)
|
|
|
|
|
filters = {}
|
|
|
|
|
permissions: dict[str, int] = {}
|
|
|
|
|
filters: dict[str, t.Callable[[tarfile.TarInfo], t.Optional[tarfile.TarInfo]]] = {}
|
|
|
|
|
|
|
|
|
|
def apply_permissions(tar_info: tarfile.TarInfo, mode: int) -> t.Optional[tarfile.TarInfo]:
|
|
|
|
|
"""
|
|
|
|
|
Apply the specified permissions to the given file.
|
|
|
|
|
Existing file type bits are preserved.
|
|
|
|
|
"""
|
|
|
|
|
tar_info.mode &= ~(stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
|
|
|
|
|
tar_info.mode |= mode
|
|
|
|
|
|
|
|
|
|
return tar_info
|
|
|
|
|
|
|
|
|
|
def make_executable(tar_info: tarfile.TarInfo) -> t.Optional[tarfile.TarInfo]:
|
|
|
|
|
"""Make the given file executable."""
|
|
|
|
|
tar_info.mode |= stat.S_IXUSR | stat.S_IXOTH | stat.S_IXGRP
|
|
|
|
|
"""
|
|
|
|
|
Make the given file executable and readable by all, and writeable by the owner.
|
|
|
|
|
Existing file type bits are preserved.
|
|
|
|
|
This ensures consistency of test results when using unprivileged users.
|
|
|
|
|
"""
|
|
|
|
|
return apply_permissions(
|
|
|
|
|
tar_info,
|
|
|
|
|
stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH |
|
|
|
|
|
stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH |
|
|
|
|
|
stat.S_IWUSR
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def make_non_executable(tar_info: tarfile.TarInfo) -> t.Optional[tarfile.TarInfo]:
|
|
|
|
|
"""
|
|
|
|
|
Make the given file readable by all, and writeable by the owner.
|
|
|
|
|
Existing file type bits are preserved.
|
|
|
|
|
This ensures consistency of test results when using unprivileged users.
|
|
|
|
|
"""
|
|
|
|
|
return apply_permissions(
|
|
|
|
|
tar_info,
|
|
|
|
|
stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH |
|
|
|
|
|
stat.S_IWUSR
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def detect_permissions(tar_info: tarfile.TarInfo) -> t.Optional[tarfile.TarInfo]:
|
|
|
|
|
"""
|
|
|
|
|
Detect and apply the appropriate permissions for a file.
|
|
|
|
|
Existing file type bits are preserved.
|
|
|
|
|
This ensures consistency of test results when using unprivileged users.
|
|
|
|
|
"""
|
|
|
|
|
if tar_info.path.startswith('ansible/'):
|
|
|
|
|
mode = permissions.get(os.path.relpath(tar_info.path, 'ansible'))
|
|
|
|
|
elif data_context().content.collection and is_subdir(tar_info.path, data_context().content.collection.directory):
|
|
|
|
|
mode = permissions.get(os.path.relpath(tar_info.path, data_context().content.collection.directory))
|
|
|
|
|
else:
|
|
|
|
|
mode = None
|
|
|
|
|
|
|
|
|
|
if mode:
|
|
|
|
|
tar_info = apply_permissions(tar_info, mode)
|
|
|
|
|
elif tar_info.mode & (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH):
|
|
|
|
|
# If any execute bit is set, treat the file as executable.
|
|
|
|
|
# This ensures that sanity tests which check execute bits behave correctly.
|
|
|
|
|
tar_info = make_executable(tar_info)
|
|
|
|
|
else:
|
|
|
|
|
tar_info = make_non_executable(tar_info)
|
|
|
|
|
|
|
|
|
|
return tar_info
|
|
|
|
|
|
|
|
|
|
if not ANSIBLE_SOURCE_ROOT:
|
|
|
|
@ -85,10 +141,15 @@ def create_payload(args: CommonConfig, dst_path: str) -> None:
|
|
|
|
|
# there are no extra files when testing ansible itself
|
|
|
|
|
extra_files = []
|
|
|
|
|
|
|
|
|
|
payload_config = PayloadConfig(
|
|
|
|
|
files=content_files,
|
|
|
|
|
permissions=permissions,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
for callback in data_context().payload_callbacks:
|
|
|
|
|
# execute callbacks only on the content paths
|
|
|
|
|
# this is done before placing them in the appropriate subdirectory (see below)
|
|
|
|
|
callback(content_files)
|
|
|
|
|
callback(payload_config)
|
|
|
|
|
|
|
|
|
|
# place ansible source files under the 'ansible' directory on the delegated host
|
|
|
|
|
files = [(src, os.path.join('ansible', dst)) for src, dst in files]
|
|
|
|
@ -109,7 +170,7 @@ def create_payload(args: CommonConfig, dst_path: str) -> None:
|
|
|
|
|
with tarfile.open(dst_path, mode='w:gz', compresslevel=4, format=tarfile.GNU_FORMAT) as tar:
|
|
|
|
|
for src, dst in files:
|
|
|
|
|
display.info('%s -> %s' % (src, dst), verbosity=4)
|
|
|
|
|
tar.add(src, dst, filter=filters.get(dst))
|
|
|
|
|
tar.add(src, dst, filter=filters.get(dst, detect_permissions))
|
|
|
|
|
|
|
|
|
|
duration = time.time() - start
|
|
|
|
|
payload_size_bytes = os.path.getsize(dst_path)
|
|
|
|
|