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

Add --ident option to process command #939

Merged
merged 1 commit into from Dec 16, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions ansible_runner/__main__.py
Expand Up @@ -656,6 +656,14 @@ def main(sys_args=None):
help="Receive the output of remote ansible-runner work and distribute the results"
)
add_args_to_parser(process_subparser, DEFAULT_CLI_ARGS['positional_args'])
process_subparser.add_argument(
"-i", "--ident",
default=None,
help=(
"An identifier to use as a subdirectory when saving artifacts. "
"Generally intended to match the --ident passed to the transmit command."
)
)

# generic args for all subparsers
add_args_to_parser(run_subparser, DEFAULT_CLI_ARGS['generic_args'])
Expand Down
11 changes: 8 additions & 3 deletions ansible_runner/streaming.py
Expand Up @@ -178,9 +178,14 @@ def __init__(self, _input=None, status_handler=None, event_handler=None,
settings = {}
self.config = MockConfig(settings)

artifact_dir = kwargs.get('artifact_dir')
self.artifact_dir = os.path.abspath(
artifact_dir or os.path.join(self.private_data_dir, 'artifacts'))
if kwargs.get('artifact_dir'):
self.artifact_dir = os.path.abspath(kwargs.get('artifact_dir'))
else:
project_artifacts = os.path.abspath(os.path.join(self.private_data_dir, 'artifacts'))
if kwargs.get('ident'):
self.artifact_dir = os.path.join(project_artifacts, "{}".format(kwargs.get('ident')))
else:
self.artifact_dir = project_artifacts

self.status_handler = status_handler
self.event_handler = event_handler
Expand Down
11 changes: 11 additions & 0 deletions docs/remote_jobs.rst
Expand Up @@ -55,6 +55,17 @@ There is otherwise no automatic cleanup of images used by a run,
even if ``container_auth_data`` is used to pull from a private container registry.
To be sure that layers are deleted as well, the ``--image-prune`` flag is necessary.

Artifact Directory Specification
--------------------------------

The ``worker`` command does not write artifacts, these are streamed instead, and
the ``process`` command is what ultimately writes the artifacts folder contents.

With the default behavior, ``ansible-runner process ./demo`` would write artifacts to ``./demo/artifacts``.
If you wish to better align with normal ansible-runner use, you can pass the
``--ident`` option to save to a subfolder, so ``ansible-runner process ./demo --ident=43``
would extract artifacts to the folder ``./demo/artifacts/43``.

Python API
----------

Expand Down
39 changes: 35 additions & 4 deletions test/integration/test_transmit_worker_process.py
Expand Up @@ -169,7 +169,7 @@ def process_method(results_sockfile_read):
self.check_artifacts(str(process_dir), job_type)


@pytest.fixture()
@pytest.fixture
def transmit_stream(project_fixtures, tmp_path):
outgoing_buffer = tmp_path / 'buffer'
outgoing_buffer.touch()
Expand All @@ -179,9 +179,26 @@ def transmit_stream(project_fixtures, tmp_path):
transmitter = Transmitter(_output=f, private_data_dir=transmit_dir, playbook='debug.yml')
status, rc = transmitter.run()

assert rc in (None, 0)
assert status == 'unstarted'
return outgoing_buffer
assert rc in (None, 0)
assert status == 'unstarted'
return outgoing_buffer


@pytest.fixture
def worker_stream(transmit_stream, tmp_path):
ingoing_buffer = tmp_path / 'buffer2' # basically how some demos work
ingoing_buffer.touch()

worker_dir = tmp_path / 'worker_dir'
worker_dir.mkdir()
with transmit_stream.open('rb') as out:
with ingoing_buffer.open('wb') as f:
worker = Worker(_input=out, _output=f, private_data_dir=worker_dir)
status, rc = worker.run()

assert rc in (None, 0)
assert status == 'successful'
return ingoing_buffer


def test_worker_without_delete_no_dir(tmp_path, cli, transmit_stream):
Expand Down Expand Up @@ -247,6 +264,20 @@ def test_worker_delete_dir_exists(tmp_path, cli, transmit_stream):
assert not worker_dir.joinpath('project', 'debug.yml').exists()


def test_process_with_custom_ident(tmp_path, cli, worker_stream):
process_dir = tmp_path / 'for_process'
process_dir.mkdir()

with open(worker_stream, 'rb') as f:
process_args = ['process', str(process_dir), '--ident', 'custom_ident']
r = cli(process_args, stdin=f)

assert 'Hello world!' in r.stdout
assert (process_dir / 'artifacts').exists()
assert (process_dir / 'artifacts' / 'custom_ident').exists()
assert (process_dir / 'artifacts' / 'custom_ident' / 'job_events').exists()


def test_missing_private_dir_transmit(tmpdir):
outgoing_buffer = io.BytesIO()

Expand Down