utils_devops 0.1.148__tar.gz → 0.1.150__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {utils_devops-0.1.148 → utils_devops-0.1.150}/PKG-INFO +1 -1
  2. {utils_devops-0.1.148 → utils_devops-0.1.150}/pyproject.toml +1 -1
  3. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/core/envs.py +3 -3
  4. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/extras/ssh_ops.py +72 -2
  5. {utils_devops-0.1.148 → utils_devops-0.1.150}/README.md +0 -0
  6. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/__init__.py +0 -0
  7. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/core/__init__.py +0 -0
  8. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/core/datetimes.py +0 -0
  9. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/core/files.py +0 -0
  10. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/core/logs.py +0 -0
  11. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/core/script_helpers.py +0 -0
  12. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/core/strings.py +0 -0
  13. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/core/systems.py +0 -0
  14. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/extras/__init__.py +0 -0
  15. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/extras/aws_ops.py +0 -0
  16. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/extras/docker_ops.py +0 -0
  17. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/extras/git_ops.py +0 -0
  18. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/extras/interaction_ops.py +0 -0
  19. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/extras/metrics_ops.py +0 -0
  20. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/extras/network_ops.py +0 -0
  21. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/extras/nginx_ops.py +0 -0
  22. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/extras/notification_ops.py +0 -0
  23. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/extras/performance_ops.py +0 -0
  24. {utils_devops-0.1.148 → utils_devops-0.1.150}/src/utils_devops/extras/vault_ops.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: utils_devops
3
- Version: 0.1.148
3
+ Version: 0.1.150
4
4
  Summary: Lightweight DevOps utilities for automation scripts: config editing (YAML/JSON/INI/.env), templating, diffing, and CLI tools
5
5
  License: MIT
6
6
  Keywords: devops,automation,nginx,cli,jinja2,yaml,config,diff,templating,logging,docker,compose,file-ops
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "utils_devops"
3
- version = "0.1.148" # Bumped for new string features + diffing
3
+ version = "0.1.150" # Bumped for new string features + diffing
4
4
  description = "Lightweight DevOps utilities for automation scripts: config editing (YAML/JSON/INI/.env), templating, diffing, and CLI tools"
5
5
  authors = ["Hamed Sheikhan <sh.sheikhan.m@gmail.com>"]
6
6
  license = "MIT"
@@ -1,5 +1,5 @@
1
1
  """
2
- Environment operations for utils_devops (env_ops module).
2
+ Environment operations for utils_devops (envs module).
3
3
 
4
4
  Provides utilities to manage .env files and system environment variables,
5
5
  run commands with specific env settings, and safely update env files with
@@ -66,13 +66,13 @@ class EnvOpsError(Exception):
66
66
 
67
67
 
68
68
  def help() -> None:
69
- """Print a short index of the env_ops API for interactive use."""
69
+ """Print a short index of the envs API for interactive use."""
70
70
  print(
71
71
  """
72
72
  DevOps Utils — Environment Operations Module
73
73
  Key functions:
74
74
  EnvOpsError: Custom exception for environment operations failures.
75
- help() -> None: Print a short index of the env_ops API for interactive use.
75
+ help() -> None: Print a short index of the envs API for interactive use.
76
76
 
77
77
  Loading Environment Files:
78
78
  load_env_file(file_path: Union[str, Path], as_dict: bool = True) -> Union[Dict[str, str], List[str]]: Load a .env file and return a dict of key->value or list of lines.
@@ -528,6 +528,71 @@ def _resolve_ssh_key(key_input: Optional[Union[str, Path]]) -> Tuple[Optional[Pa
528
528
  # **IMPORTANT**: Preserve any newlines in the content
529
529
  return None, key_input_str
530
530
 
531
+ def _inject_environment_variables(
532
+ environment: Optional[Dict[str, str]] = None,
533
+ base_command: str = ""
534
+ ) -> str:
535
+ """
536
+ Creates a command string that safely injects environment variables.
537
+ """
538
+ if not environment:
539
+ return base_command
540
+
541
+ env_lines = []
542
+ if systems.is_linux:
543
+ # Linux syntax: export VAR='value'
544
+ for key, value in environment.items():
545
+ print(f"DEBUG _inject_environment_variables: key='{key}', value='{value}', type={type(value)}") # DEBUG
546
+ escaped_value = value.replace("'", "'\"'\"'")
547
+ env_lines.append(f"export {key}='{escaped_value}'")
548
+ env_setup = " && ".join(env_lines)
549
+ prefix = f"{env_setup} && "
550
+ elif systems.is_windows:
551
+ # Windows syntax (PowerShell)
552
+ for key, value in environment.items():
553
+ print(f"DEBUG _inject_environment_variables: key='{key}', value='{value}', type={type(value)}") # DEBUG
554
+ escaped_value = value.replace("'", "''").replace("`", "``")
555
+ env_lines.append(f"$env:{key}='{escaped_value}'")
556
+ env_setup = "; ".join(env_lines)
557
+ prefix = f"{env_setup}; "
558
+
559
+ return f"{prefix}{base_command}"
560
+
561
+ def _detect_remote_os(client) -> str:
562
+ """
563
+ Detect the operating system of the remote SSH host.
564
+ Returns: "linux", "windows", or "unknown"
565
+ """
566
+ try:
567
+ # Try Linux command first
568
+ stdin, stdout, stderr = client.exec_command("uname -s", timeout=5)
569
+ output = stdout.read().decode('utf-8', errors='ignore').strip().lower()
570
+ if "linux" in output or "darwin" in output:
571
+ return "linux"
572
+ except:
573
+ pass
574
+
575
+ try:
576
+ # Try Windows command
577
+ stdin, stdout, stderr = client.exec_command("ver", timeout=5)
578
+ output = stdout.read().decode('utf-8', errors='ignore').strip().lower()
579
+ if "windows" in output or "microsoft" in output:
580
+ return "windows"
581
+ except:
582
+ pass
583
+
584
+ # Try PowerShell (Windows)
585
+ try:
586
+ stdin, stdout, stderr = client.exec_command("Get-Host", timeout=5)
587
+ output = stdout.read().decode('utf-8', errors='ignore').strip().lower()
588
+ if "powershell" in output or "windows" in output:
589
+ return "windows"
590
+ except:
591
+ pass
592
+
593
+ # Default to linux (backward compatibility)
594
+ return "linux"
595
+
531
596
  def ssh_execute_command(
532
597
  host: str,
533
598
  command: Union[str, List[str]],
@@ -569,10 +634,15 @@ def ssh_execute_command(
569
634
  else:
570
635
  command_str = command
571
636
 
637
+ with ssh_connect(
638
+ host, username, password, key_file, port, **kwargs
639
+ ) as client:
640
+ # 1. DETECT REMOTE OS
641
+ remote_os = _detect_remote_os(client)
642
+
572
643
  # Add environment variables
573
644
  if environment:
574
- env_vars = " ".join([f"export {k}='{v}'" for k, v in environment.items()])
575
- command_str = f"{env_vars}; {command_str}"
645
+ command_str = _inject_environment_variables(environment, command_str,remote_os=remote_os)
576
646
 
577
647
  # Add sudo
578
648
  if sudo:
File without changes