Skip to content

Commit 04aaed2

Browse files
Merge from aws/aws-sam-cli/develop
2 parents 6eb0a1b + 41fd19e commit 04aaed2

File tree

13 files changed

+954
-1595
lines changed

13 files changed

+954
-1595
lines changed

samcli/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
SAM CLI version
33
"""
44

5-
__version__ = "1.145.1"
5+
__version__ = "1.145.2"

samcli/lib/telemetry/metric.py

Lines changed: 68 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@
4444
"""
4545
_METRICS = dict()
4646

47+
# Global container socket and runtime information for telemetry
48+
# This persists across context boundaries to ensure accurate telemetry reporting
49+
_CONTAINER_RUNTIME_INFO: Dict[str, Optional[str]] = {"container_socket_path": None, "admin_preference": None}
50+
4751

4852
@dataclass
4953
class ProjectDetails:
@@ -241,9 +245,8 @@ def _send_command_run_metrics(ctx: Context, duration: int, exit_reason: str, exi
241245
# Add container engine information for all command runs
242246
metric_specific_attributes["containerEngine"] = metric._get_container_host()
243247

244-
# Add admin container preference (None if not set)
245-
admin_pref = getattr(ctx, "admin_container_preference", None)
246-
metric_specific_attributes["adminContainerPreference"] = admin_pref
248+
# Add admin container preference from global storage (set by container client factory)
249+
metric_specific_attributes["adminContainerPreference"] = metric._get_container_admin_preference()
247250

248251
metric.add_data("metricSpecificAttributes", metric_specific_attributes)
249252
# Metric about command's execution characteristics
@@ -404,6 +407,37 @@ def emit_all_metrics():
404407
emit_metric(key)
405408

406409

410+
def set_container_socket_host_telemetry(
411+
container_socket_path: Optional[str] = None, admin_preference: Optional[str] = None
412+
):
413+
"""
414+
Set container socket path and admin preference for telemetry collection.
415+
416+
This function stores container socket information globally to ensure it persists
417+
across context boundaries and is available during telemetry collection.
418+
419+
Args:
420+
container_socket_path: The socket path being used (e.g., "unix:///var/run/docker.sock", "unix://~/.finch/finch.sock")
421+
admin_preference: The administrator's container preference (e.g., "finch", "docker", None)
422+
"""
423+
if container_socket_path is not None:
424+
_CONTAINER_RUNTIME_INFO["container_socket_path"] = container_socket_path
425+
LOG.debug(f"Set global container socket path: container_socket_path={container_socket_path}")
426+
if admin_preference is not None:
427+
_CONTAINER_RUNTIME_INFO["admin_preference"] = admin_preference
428+
LOG.debug(f"Set global container runtime info: admin_preference={admin_preference}")
429+
430+
431+
def get_container_runtime_telemetry_info() -> Dict[str, Optional[str]]:
432+
"""
433+
Get container socket path and runtime information for telemetry collection.
434+
435+
Returns:
436+
Dict containing container_socket_path and admin_preference
437+
"""
438+
return _CONTAINER_RUNTIME_INFO
439+
440+
407441
class Metric:
408442
"""
409443
Metric class to store metric data and adding common attributes
@@ -487,35 +521,31 @@ def _get_execution_environment(self) -> str:
487521

488522
def _get_container_host(self) -> str:
489523
"""
490-
Returns the container engine being used with context-first detection:
491-
1. If actual runtime type is stored in context, use that (for native SAM CLI clients like Finch)
524+
Returns the container engine being used with socket path detection:
525+
1. Check global container socket path (set by container client factory)
492526
2. Otherwise, fall back to DOCKER_HOST environment variable detection (for custom configurations)
493527
"""
494-
try:
495-
# First, try to get the actual runtime type from context (same pattern as admin_container_preference)
496-
ctx = Context.get_current_context()
497-
if ctx:
498-
actual_runtime = getattr(ctx, "actual_container_runtime", None)
499-
if actual_runtime:
500-
return str(actual_runtime)
501-
except (RuntimeError, ImportError):
502-
# No Click context available
503-
pass
528+
# First, check global container socket path (set by container client factory)
529+
global_runtime_info = get_container_runtime_telemetry_info()
530+
if global_runtime_info["container_socket_path"]:
531+
LOG.debug(f"Using global container socket path: {global_runtime_info['container_socket_path']}")
532+
return self._get_container_engine_from_socket_path(global_runtime_info["container_socket_path"])
504533

505534
# Fall back to environment variable detection for custom DOCKER_HOST configurations
506-
LOG.debug("No container runtime in context, falling back to DOCKER_HOST detection")
507-
return self._get_container_host_from_env()
535+
docker_host = os.environ.get("DOCKER_HOST", "")
536+
LOG.debug(f"No container socket path in global storage, falling back to DOCKER_HOST detection: {docker_host}")
537+
return self._get_container_engine_from_socket_path(docker_host)
508538

509-
def _get_container_host_from_env(self) -> str:
539+
def _get_container_engine_from_socket_path(self, socket_path: str) -> str:
510540
"""
511-
Detect container engine from environment variables for custom DOCKER_HOST configurations.
512-
This handles cases where customers manually set DOCKER_HOST to non-native runtimes.
541+
Detect container engine from socket path.
542+
This handles detection for any socket path, whether from stored telemetry or environment.
513543
514544
Translation:
515545
Value Final Value
516546
517-
# Case 1: Not set
518-
- (unset) -> docker-default
547+
# Case 1: Empty/None
548+
- "" -> docker-default
519549
520550
# Case 2: Check Path-specific
521551
- unix://~/.colima/default/docker.sock -> colima
@@ -536,38 +566,45 @@ def _get_container_host_from_env(self) -> str:
536566
# Case 5: Other
537567
- other value -> unknown
538568
"""
539-
# Read current DOCKER_HOST directly from environment instead of cached value
540-
docker_host = os.environ.get("DOCKER_HOST", "")
541-
542-
if not docker_host:
569+
if not socket_path:
543570
return "docker-default"
544571

545-
docker_host = docker_host.lower()
572+
socket_path_lower = socket_path.lower()
546573

547574
# Path-specific mappings (checked first for specificity)
548575
path_map = {".colima/": "colima", ".lima/": "lima", ".orbstack/": "orbstack", ".rd/": "rancher-desktop"}
549576

550577
# Check path-specific patterns first
551578
for path, engine in path_map.items():
552-
if path in docker_host and docker_host.endswith("docker.sock"):
579+
if path in socket_path_lower and socket_path_lower.endswith("docker.sock"):
553580
return engine
554581

555582
# Socket mappings
556583
socket_map = {"docker.sock": "docker", "finch.sock": "finch", "podman.sock": "podman"}
557584

558585
# Check socket patterns
559586
for sock, engine in socket_map.items():
560-
if docker_host.endswith(sock):
587+
if socket_path_lower.endswith(sock):
561588
return engine
562589

563590
# TCP patterns
564-
if docker_host.startswith("tcp://"):
591+
if socket_path_lower.startswith("tcp://"):
565592
local_hosts = ["localhost:", "127.0.0.1:"]
566-
is_local = any(host in docker_host for host in local_hosts)
593+
is_local = any(host in socket_path_lower for host in local_hosts)
567594
return "tcp-local" if is_local else "tcp-remote"
568595

569596
return "unknown"
570597

598+
def _get_container_admin_preference(self) -> Optional[str]:
599+
"""
600+
Get the administrator's container preference from global storage.
601+
602+
Returns:
603+
Optional[str]: Admin preference value ("finch", "docker", "other", or None)
604+
"""
605+
global_runtime_info = get_container_runtime_telemetry_info()
606+
return global_runtime_info["admin_preference"]
607+
571608

572609
class MetricDataNotList(Exception):
573610
pass

samcli/lib/utils/system_info.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ def _gather_container_engine_info() -> str:
6262

6363
# Check if we're using Finch by looking at the runtime type
6464
if hasattr(client, "get_runtime_type") and client.get_runtime_type() == "finch":
65-
return f"Finch(v{version})"
65+
return f"Finch({version})"
6666
else:
67-
return f"Docker({version})"
67+
return f"Docker(v{version})"
6868
except Exception:
6969
return "Not available"
7070

0 commit comments

Comments
 (0)