WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ddev/changelog.d/22042.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improve logging and UX for Docker Agent lifecycle commands (start-up, local packages, post-install, stop) in E2E testing
13 changes: 11 additions & 2 deletions ddev/src/ddev/cli/terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,17 @@ def display_debug(self, text='', stderr=True, indent=None, link=None, **kwargs):

self._output(f'DEBUG: {text}', None, stderr=stderr, indent=indent, link=link, **kwargs)

def display_header(self, title=''):
self.console.rule(Text(title, self._style_level_success))
def display_header(
self,
title='',
text_style: Style | str | None = None,
characters: str | None = None,
line_style: Style | str | None = None,
):
text_style = text_style or self._style_level_success
characters = characters or "─"
line_style = line_style or "rule.line"
self.console.rule(Text(title, text_style), characters=characters, style=line_style)

def display_markdown(self, text, stderr=False, **kwargs):
from rich.markdown import Markdown
Expand Down
75 changes: 53 additions & 22 deletions ddev/src/ddev/e2e/agent/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,34 @@ def _run_command(self, command: list[str], **kwargs) -> subprocess.CompletedProc
with EnvVars({'DOCKER_CLI_HINTS': 'false'}):
return self.platform.run_command(command, **kwargs)

def _execute_lifecycle_command(
self, command: list[str], start_message: str, end_message_prefix: str, error_message: str
) -> None:
"""
Execute a lifecycle command and display status messages.

:param command: The command to execute.
:param start_message: The message to display before the command starts.
:param end_message_prefix: The prefix for the message displayed after the command finishes.
The full message will be "{prefix} {status} (code: {code})".
:param error_message: The error message to raise if the command fails.
"""
self.app.display_header(start_message)
process = self._run_command(command)
return_code = process.returncode

text_style = self.app._style_level_error if return_code else self.app._style_level_success
status_text = 'failed' if return_code else 'succeeded'
self.app.display_header(
f'{end_message_prefix} {status_text} (code: {return_code})',
text_style=text_style,
characters='.',
)

if return_code:
self._show_logs()
raise RuntimeError(error_message)

def _show_logs(self) -> None:
self._run_command(['docker', 'logs', self._container_name])

Expand Down Expand Up @@ -276,43 +304,46 @@ def _initialize(self, command, local_packages, start_commands, post_install_comm
if start_commands:
for start_command in start_commands:
formatted_command = self._format_command(self.platform.modules.shlex.split(start_command))
process = self._run_command(formatted_command)
if process.returncode:
self._show_logs()
raise RuntimeError(f'Unable to run start-up command in Agent container `{self._container_name}`')
self._execute_lifecycle_command(
formatted_command,
f'Running start-up command: {start_command}',
'Start-up command',
f'Unable to run start-up command in Agent container `{self._container_name}`\n',
)

if local_packages:
base_pip_command = self._format_command(
[self._python_path, '-m', 'pip', 'install', '--disable-pip-version-check', '-e']
)
for local_package, features in local_packages.items():
package_mount = f'{self._package_mount_dir}{local_package.name}{features}'
process = self._run_command([*base_pip_command, package_mount])
if process.returncode:
self._show_logs()
raise RuntimeError(
f'Unable to install package `{local_package.name}` in Agent container `{self._container_name}`'
)
self._execute_lifecycle_command(
[*base_pip_command, package_mount],
f'Installing local package: {local_package.name}{features}',
'Package installation',
f'Unable to install package `{local_package.name}` in Agent container `{self._container_name}`',
)

if post_install_commands:
for post_install_command in post_install_commands:
formatted_command = self._format_command(self.platform.modules.shlex.split(post_install_command))
process = self._run_command(formatted_command)
if process.returncode:
self._show_logs()
raise RuntimeError(
f'Unable to run post-install command in Agent container `{self._container_name}`'
)
self._execute_lifecycle_command(
formatted_command,
f'Running post-install command: {post_install_command}',
'Post-install command',
f'Unable to run post-install command in Agent container `{self._container_name}`',
)

def stop(self) -> None:
stop_commands = self.metadata.get('stop_commands', [])
if stop_commands:
if stop_commands := self.metadata.get('stop_commands', []):
for stop_command in stop_commands:
formatted_command = self._format_command(self.platform.modules.shlex.split(stop_command))
process = self._run_command(formatted_command)
if process.returncode:
self._show_logs()
raise RuntimeError(f'Unable to run stop command in Agent container `{self._container_name}`')
self._execute_lifecycle_command(
formatted_command,
f'Running stop command: {stop_command}',
'Stop command',
f'Unable to run stop command in Agent container `{self._container_name}`',
)

for command in (
['docker', 'stop', '-t', '0', self._container_name],
Expand Down
Loading