mirror of
https://github.com/containers/ansible-podman-collections.git
synced 2026-02-04 07:11:49 +00:00
Improve performance
Signed-off-by: Sagi Shnaidman <sshnaidm@redhat.com>
This commit is contained in:
parent
705f10d8f2
commit
1755665d37
2 changed files with 40 additions and 97 deletions
|
|
@ -159,9 +159,7 @@ class Connection(ConnectionBase):
|
|||
self._executable_path = None
|
||||
self._task_uuid = to_text(kwargs.get("task_uuid", ""))
|
||||
|
||||
# Initialize caches
|
||||
self._command_cache = {}
|
||||
self._container_validation_cache = {}
|
||||
# No pre-validation caches to preserve performance
|
||||
|
||||
display.vvvv("Using buildah connection from collection", host=self._container_id)
|
||||
|
||||
|
|
@ -230,14 +228,13 @@ class Connection(ConnectionBase):
|
|||
display.vvvvv(f"STDERR: {stderr}", host=self._container_id)
|
||||
display.vvvvv(f"RC: {process.returncode}", host=self._container_id)
|
||||
|
||||
stdout = to_bytes(stdout, errors="surrogate_or_strict")
|
||||
stderr = to_bytes(stderr, errors="surrogate_or_strict")
|
||||
|
||||
if check_rc and process.returncode != 0:
|
||||
if process.returncode != 0:
|
||||
error_msg = to_text(stderr, errors="surrogate_or_strict").strip()
|
||||
if "no such container" in error_msg.lower() or "container not known" in error_msg.lower():
|
||||
lower = error_msg.lower()
|
||||
if "no such container" in lower or "container not known" in lower or "does not exist" in lower:
|
||||
raise ContainerNotFoundError(f"Container '{self._container_id}' not found")
|
||||
raise BuildahConnectionError(f"Command failed (rc={process.returncode}): {error_msg}")
|
||||
if check_rc:
|
||||
raise BuildahConnectionError(f"Command failed (rc={process.returncode}): {error_msg}")
|
||||
|
||||
return process.returncode, stdout, stderr
|
||||
|
||||
|
|
@ -252,21 +249,7 @@ class Connection(ConnectionBase):
|
|||
stdout_fd.close()
|
||||
raise BuildahConnectionError(f"Command execution failed: {e}")
|
||||
|
||||
def _validate_container(self):
|
||||
"""Validate that the container exists using a fast check"""
|
||||
if self._container_id in self._container_validation_cache:
|
||||
return self._container_validation_cache[self._container_id]
|
||||
|
||||
# Use inspect as an existence check only, avoid JSON parsing
|
||||
rc, _stdout, _stderr = self._run_buildah_command(
|
||||
["inspect", self._container_id], include_container=False, check_rc=False
|
||||
)
|
||||
if rc != 0:
|
||||
raise ContainerNotFoundError(f"Container '{self._container_id}' not found")
|
||||
|
||||
self._container_validation_cache[self._container_id] = True
|
||||
display.vvv("Container validation successful", host=self._container_id)
|
||||
return True
|
||||
# No proactive validation; rely on operation failures for performance
|
||||
|
||||
def _setup_mount_point(self):
|
||||
"""Attempt to mount container filesystem for direct access"""
|
||||
|
|
@ -297,8 +280,7 @@ class Connection(ConnectionBase):
|
|||
|
||||
display.vvv(f"Connecting to buildah container: {self._container_id}", host=self._container_id)
|
||||
|
||||
# Validate container exists and is accessible (fast)
|
||||
self._validate_container()
|
||||
# No proactive validation to avoid extra subprocess overhead
|
||||
|
||||
self._connected = True
|
||||
display.vvv("Connection established successfully", host=self._container_id)
|
||||
|
|
@ -312,7 +294,6 @@ class Connection(ConnectionBase):
|
|||
|
||||
cmd_args_list = shlex.split(to_native(cmd, errors="surrogate_or_strict"))
|
||||
run_cmd = ["run"]
|
||||
|
||||
# Handle user specification
|
||||
if self.get_option("remote_user") and self.get_option("remote_user") != "root":
|
||||
run_cmd.extend(["--user", self.get_option("remote_user")])
|
||||
|
|
@ -339,24 +320,13 @@ class Connection(ConnectionBase):
|
|||
|
||||
run_cmd.extend(cmd_args_list)
|
||||
|
||||
try:
|
||||
# Use include_container=False since we already added container name
|
||||
rc, stdout, stderr = self._run_buildah_command(run_cmd, input_data=in_data, include_container=False)
|
||||
# Use include_container=False since we already added container name
|
||||
rc, stdout, stderr = self._run_buildah_command(run_cmd, input_data=in_data, include_container=False)
|
||||
|
||||
# Auto-commit if enabled and command succeeded
|
||||
if rc == 0 and self.get_option("auto_commit"):
|
||||
self._auto_commit_changes()
|
||||
return rc, stdout, stderr
|
||||
|
||||
except ContainerNotFoundError:
|
||||
# Container might have been removed, invalidate cache and retry once
|
||||
if self._container_id in self._container_validation_cache:
|
||||
del self._container_validation_cache[self._container_id]
|
||||
self._connected = False
|
||||
self._connect()
|
||||
rc, stdout, stderr = self._run_buildah_command(run_cmd, input_data=in_data, include_container=False)
|
||||
return rc, stdout, stderr
|
||||
raise
|
||||
# Auto-commit if enabled and command succeeded
|
||||
if rc == 0 and self.get_option("auto_commit"):
|
||||
self._auto_commit_changes()
|
||||
return rc, stdout, stderr
|
||||
|
||||
def _auto_commit_changes(self):
|
||||
"""Automatically commit changes if enabled"""
|
||||
|
|
|
|||
|
|
@ -111,6 +111,12 @@ DOCUMENTATION = """
|
|||
type: str
|
||||
vars:
|
||||
- name: ansible_podman_privilege_escalation
|
||||
working_directory:
|
||||
description:
|
||||
- Working directory for commands executed in the container.
|
||||
type: str
|
||||
vars:
|
||||
- name: ansible_podman_working_directory
|
||||
"""
|
||||
|
||||
import os
|
||||
|
|
@ -153,9 +159,7 @@ class Connection(ConnectionBase):
|
|||
self._executable_path = None
|
||||
self._task_uuid = to_text(kwargs.get("task_uuid", ""))
|
||||
|
||||
# Initialize caches
|
||||
self._command_cache = {}
|
||||
self._container_validation_cache = {}
|
||||
# No pre-validation caches to preserve performance
|
||||
|
||||
display.vvvv("Using podman connection from collection", host=self._container_id)
|
||||
|
||||
|
|
@ -215,39 +219,26 @@ class Connection(ConnectionBase):
|
|||
display.vvvvv(f"STDERR: {stderr}", host=self._container_id)
|
||||
display.vvvvv(f"RC: {process.returncode}", host=self._container_id)
|
||||
|
||||
stdout = to_bytes(stdout, errors="surrogate_or_strict")
|
||||
stderr = to_bytes(stderr, errors="surrogate_or_strict")
|
||||
|
||||
if check_rc and process.returncode != 0:
|
||||
if process.returncode != 0:
|
||||
error_msg = to_text(stderr, errors="surrogate_or_strict").strip()
|
||||
if "no such container" in error_msg.lower():
|
||||
lower = error_msg.lower()
|
||||
if "no such container" in lower or "does not exist" in lower or "container not known" in lower:
|
||||
self._connected = False
|
||||
raise ContainerNotFoundError(f"Container '{self._container_id}' not found")
|
||||
raise PodmanConnectionError(f"Command failed (rc={process.returncode}): {error_msg}")
|
||||
if check_rc:
|
||||
raise PodmanConnectionError(f"Command failed (rc={process.returncode}): {error_msg}")
|
||||
|
||||
return process.returncode, stdout, stderr
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
process.kill()
|
||||
timeout_val = self.get_option('container_timeout')
|
||||
timeout_val = self.get_option("container_timeout")
|
||||
self._connected = False
|
||||
raise PodmanConnectionError(f"Command timeout after {timeout_val}s")
|
||||
except Exception as e:
|
||||
raise PodmanConnectionError(f"Command execution failed: {e}")
|
||||
|
||||
def _validate_container(self):
|
||||
"""Validate that the container exists using a fast check"""
|
||||
if self._container_id in self._container_validation_cache:
|
||||
return self._container_validation_cache[self._container_id]
|
||||
|
||||
# Fast existence check avoids expensive JSON parsing
|
||||
rc, _stdout, _stderr = self._run_podman_command(
|
||||
["container", "exists", self._container_id], include_container=False, check_rc=False
|
||||
)
|
||||
if rc != 0:
|
||||
raise ContainerNotFoundError(f"Container '{self._container_id}' not found")
|
||||
|
||||
self._container_validation_cache[self._container_id] = True
|
||||
display.vvv("Container validation successful", host=self._container_id)
|
||||
return True
|
||||
# No proactive validation; rely on operation failures for performance
|
||||
|
||||
def _setup_mount_point(self):
|
||||
"""Attempt to mount container filesystem for direct access (lightweight)"""
|
||||
|
|
@ -281,9 +272,6 @@ class Connection(ConnectionBase):
|
|||
|
||||
display.vvv(f"Connecting to container: {self._container_id}", host=self._container_id)
|
||||
|
||||
# Validate container exists and is accessible (fast)
|
||||
self._validate_container()
|
||||
|
||||
self._connected = True
|
||||
display.vvv("Connection established successfully", host=self._container_id)
|
||||
|
||||
|
|
@ -319,22 +307,16 @@ class Connection(ConnectionBase):
|
|||
elif privilege_method == "su":
|
||||
cmd_args_list = ["su", "-c", " ".join(shlex.quote(arg) for arg in cmd_args_list)]
|
||||
|
||||
# Add working directory option
|
||||
workdir = self.get_option("working_directory")
|
||||
if workdir:
|
||||
exec_cmd.extend(["--workdir", workdir])
|
||||
|
||||
# Combine exec command: podman exec [options] container_id command
|
||||
full_cmd = exec_cmd + [self._container_id] + cmd_args_list
|
||||
|
||||
try:
|
||||
rc, stdout, stderr = self._run_podman_command(full_cmd, input_data=in_data, include_container=False)
|
||||
return rc, stdout, stderr
|
||||
|
||||
except ContainerNotFoundError:
|
||||
# Container might have been removed, invalidate cache and retry once
|
||||
if self._container_id in self._container_validation_cache:
|
||||
del self._container_validation_cache[self._container_id]
|
||||
self._connected = False
|
||||
self._connect()
|
||||
rc, stdout, stderr = self._run_podman_command(full_cmd, input_data=in_data, include_container=False)
|
||||
return rc, stdout, stderr
|
||||
raise
|
||||
rc, stdout, stderr = self._run_podman_command(full_cmd, input_data=in_data, include_container=False)
|
||||
return rc, stdout, stderr
|
||||
|
||||
def put_file(self, in_path, out_path):
|
||||
"""Transfer file to container using optimal method"""
|
||||
|
|
@ -357,14 +339,8 @@ class Connection(ConnectionBase):
|
|||
display.vvv(f"Mount copy failed, falling back to podman cp: {e}", host=self._container_id)
|
||||
|
||||
# Use podman cp command
|
||||
copy_cmd = ["cp", in_path, f"{self._container_id}:{out_path}"]
|
||||
|
||||
try:
|
||||
self._run_podman_command(copy_cmd, include_container=False, check_rc=True)
|
||||
except PodmanConnectionError:
|
||||
# Try with --pause=false for running containers
|
||||
copy_cmd.insert(1, "--pause=false")
|
||||
self._run_podman_command(copy_cmd, include_container=False, check_rc=True)
|
||||
copy_cmd = ["cp", "--pause=false", in_path, f"{self._container_id}:{out_path}"]
|
||||
self._run_podman_command(copy_cmd, include_container=False, check_rc=True)
|
||||
|
||||
# Change ownership if user specified
|
||||
if self.get_option("remote_user"):
|
||||
|
|
@ -404,7 +380,7 @@ class Connection(ConnectionBase):
|
|||
display.vvv(f"Mount fetch failed, falling back to podman cp: {e}", host=self._container_id)
|
||||
|
||||
# Use podman cp command
|
||||
copy_cmd = ["cp", f"{self._container_id}:{in_path}", out_path]
|
||||
copy_cmd = ["cp", "--pause=false", f"{self._container_id}:{in_path}", out_path]
|
||||
self._run_podman_command(copy_cmd, include_container=False, check_rc=True)
|
||||
|
||||
def close(self):
|
||||
|
|
@ -419,8 +395,5 @@ class Connection(ConnectionBase):
|
|||
except Exception as e:
|
||||
display.vvvv(f"Unmount failed (this is usually not critical): {e}", host=self._container_id)
|
||||
|
||||
# Clear caches
|
||||
self._command_cache.clear()
|
||||
|
||||
self._connected = False
|
||||
display.vvv("Connection closed", host=self._container_id)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue