vm-tool 1.0.41__tar.gz → 1.0.42__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 (120) hide show
  1. {vm_tool-1.0.41 → vm_tool-1.0.42}/PKG-INFO +1 -1
  2. {vm_tool-1.0.41 → vm_tool-1.0.42}/pyproject.toml +2 -2
  3. {vm_tool-1.0.41 → vm_tool-1.0.42}/setup.py +1 -1
  4. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/cli.py +43 -1
  5. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/runner.py +146 -0
  6. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/vm_setup/push_code_tasks.yml +25 -0
  7. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool.egg-info/PKG-INFO +1 -1
  8. {vm_tool-1.0.41 → vm_tool-1.0.42}/.devcontainer/devcontainer.json +0 -0
  9. {vm_tool-1.0.41 → vm_tool-1.0.42}/.github/dependabot.yml +0 -0
  10. {vm_tool-1.0.41 → vm_tool-1.0.42}/.github/workflows/ci.yml +0 -0
  11. {vm_tool-1.0.41 → vm_tool-1.0.42}/.github/workflows/deploy.yml +0 -0
  12. {vm_tool-1.0.41 → vm_tool-1.0.42}/.github/workflows/publish.yml +0 -0
  13. {vm_tool-1.0.41 → vm_tool-1.0.42}/.gitignore +0 -0
  14. {vm_tool-1.0.41 → vm_tool-1.0.42}/.pre-commit-config.yaml +0 -0
  15. {vm_tool-1.0.41 → vm_tool-1.0.42}/CONTRIBUTING +0 -0
  16. {vm_tool-1.0.41 → vm_tool-1.0.42}/CONTRIBUTING.md +0 -0
  17. {vm_tool-1.0.41 → vm_tool-1.0.42}/LICENSE +0 -0
  18. {vm_tool-1.0.41 → vm_tool-1.0.42}/MANIFEST.in +0 -0
  19. {vm_tool-1.0.41 → vm_tool-1.0.42}/Makefile +0 -0
  20. {vm_tool-1.0.41 → vm_tool-1.0.42}/README.md +0 -0
  21. {vm_tool-1.0.41 → vm_tool-1.0.42}/codePushToGithub.py +0 -0
  22. {vm_tool-1.0.41 → vm_tool-1.0.42}/docs/MODULE_GUIDE.md +0 -0
  23. {vm_tool-1.0.41 → vm_tool-1.0.42}/docs/deployment-approaches.md +0 -0
  24. {vm_tool-1.0.41 → vm_tool-1.0.42}/docs/ec2-github-actions-guide.md +0 -0
  25. {vm_tool-1.0.41 → vm_tool-1.0.42}/docs/features.md +0 -0
  26. {vm_tool-1.0.41 → vm_tool-1.0.42}/docs/generator.md +0 -0
  27. {vm_tool-1.0.41 → vm_tool-1.0.42}/docs/index.md +0 -0
  28. {vm_tool-1.0.41 → vm_tool-1.0.42}/docs/pipeline-generator.md +0 -0
  29. {vm_tool-1.0.41 → vm_tool-1.0.42}/docs/reference/runner.md +0 -0
  30. {vm_tool-1.0.41 → vm_tool-1.0.42}/docs/reference/ssh.md +0 -0
  31. {vm_tool-1.0.41 → vm_tool-1.0.42}/docs/ssh-key-setup.md +0 -0
  32. {vm_tool-1.0.41 → vm_tool-1.0.42}/docs/usage.md +0 -0
  33. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/README.md +0 -0
  34. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/__init__.py +0 -0
  35. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/cloud/README.md +0 -0
  36. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/cloud/__init__.py +0 -0
  37. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/cloud/ssh_identity_file.py +0 -0
  38. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/cloud/ssh_password.py +0 -0
  39. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/cloud/template_cloud_setup.py +0 -0
  40. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/deploy_full_setup.py +0 -0
  41. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/docker-compose.example.yml +0 -0
  42. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/ec2-setup.sh +0 -0
  43. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/github-actions-ec2.yml +0 -0
  44. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/github-actions-full-setup.yml +0 -0
  45. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/local/.keep +0 -0
  46. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/local/README.md +0 -0
  47. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/local/__init__.py +0 -0
  48. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/local/template_local_setup.py +0 -0
  49. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/production-deploy.sh +0 -0
  50. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/rollback.sh +0 -0
  51. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/setup.sh +0 -0
  52. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/ssh_key_management.py +0 -0
  53. {vm_tool-1.0.41 → vm_tool-1.0.42}/examples/version_check.sh +0 -0
  54. {vm_tool-1.0.41 → vm_tool-1.0.42}/mkdocs.yml +0 -0
  55. {vm_tool-1.0.41 → vm_tool-1.0.42}/molecule/default/converge.yml +0 -0
  56. {vm_tool-1.0.41 → vm_tool-1.0.42}/molecule/default/molecule.yml +0 -0
  57. {vm_tool-1.0.41 → vm_tool-1.0.42}/molecule/default/verify.yml +0 -0
  58. {vm_tool-1.0.41 → vm_tool-1.0.42}/requirements-docs.txt +0 -0
  59. {vm_tool-1.0.41 → vm_tool-1.0.42}/requirements.txt +0 -0
  60. {vm_tool-1.0.41 → vm_tool-1.0.42}/runtime.txt +0 -0
  61. {vm_tool-1.0.41 → vm_tool-1.0.42}/setup.cfg +0 -0
  62. {vm_tool-1.0.41 → vm_tool-1.0.42}/tests/conftest.py +0 -0
  63. {vm_tool-1.0.41 → vm_tool-1.0.42}/tests/integration/test_deployment.py +0 -0
  64. {vm_tool-1.0.41 → vm_tool-1.0.42}/tests/test_config.py +0 -0
  65. {vm_tool-1.0.41 → vm_tool-1.0.42}/tests/test_generator.py +0 -0
  66. {vm_tool-1.0.41 → vm_tool-1.0.42}/tests/test_health.py +0 -0
  67. {vm_tool-1.0.41 → vm_tool-1.0.42}/tests/test_history.py +0 -0
  68. {vm_tool-1.0.41 → vm_tool-1.0.42}/tests/test_logging.py +0 -0
  69. {vm_tool-1.0.41 → vm_tool-1.0.42}/tests/test_runner.py +0 -0
  70. {vm_tool-1.0.41 → vm_tool-1.0.42}/tests/test_ssh.py +0 -0
  71. {vm_tool-1.0.41 → vm_tool-1.0.42}/tests/test_state.py +0 -0
  72. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/__init__.py +0 -0
  73. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/alerting.py +0 -0
  74. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/audit.py +0 -0
  75. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/backup.py +0 -0
  76. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/benchmarking.py +0 -0
  77. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/cloud.py +0 -0
  78. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/completion.py +0 -0
  79. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/compliance.py +0 -0
  80. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/config.py +0 -0
  81. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/drift.py +0 -0
  82. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/generator.py +0 -0
  83. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/health.py +0 -0
  84. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/history.py +0 -0
  85. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/kubernetes.py +0 -0
  86. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/metrics.py +0 -0
  87. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/notifications.py +0 -0
  88. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/plugins.py +0 -0
  89. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/policy.py +0 -0
  90. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/rbac.py +0 -0
  91. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/recovery.py +0 -0
  92. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/reporting.py +0 -0
  93. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/secrets.py +0 -0
  94. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/ssh.py +0 -0
  95. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/state.py +0 -0
  96. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/strategies/__init__.py +0 -0
  97. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/strategies/ab_testing.py +0 -0
  98. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/strategies/blue_green.py +0 -0
  99. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/strategies/canary.py +0 -0
  100. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/validation.py +0 -0
  101. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/vm_setup/cleanup.yml +0 -0
  102. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/vm_setup/docker/create_docker_service.yml +0 -0
  103. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/vm_setup/docker/docker_setup.yml +0 -0
  104. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/vm_setup/docker/install_docker_and_compose.yml +0 -0
  105. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/vm_setup/docker/login_to_docker_hub.yml +0 -0
  106. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/vm_setup/github/git_configuration.yml +0 -0
  107. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/vm_setup/inventory.yml +0 -0
  108. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/vm_setup/k8s.yml +0 -0
  109. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/vm_setup/main.yml +0 -0
  110. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/vm_setup/monitoring.yml +0 -0
  111. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/vm_setup/project_service.yml +0 -0
  112. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/vm_setup/push_code.yml +0 -0
  113. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/vm_setup/setup.yml +0 -0
  114. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/vm_setup/setup_project_env.yml +0 -0
  115. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool/webhooks.py +0 -0
  116. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool.egg-info/SOURCES.txt +0 -0
  117. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool.egg-info/dependency_links.txt +0 -0
  118. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool.egg-info/entry_points.txt +0 -0
  119. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool.egg-info/requires.txt +0 -0
  120. {vm_tool-1.0.41 → vm_tool-1.0.42}/vm_tool.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vm_tool
3
- Version: 1.0.41
3
+ Version: 1.0.42
4
4
  Summary: A Comprehensive Tool for Setting Up Virtual Machines.
5
5
  Home-page: https://github.com/thesunnysinha/vm_tool
6
6
  Author: Sunny Sinha
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "vm_tool"
7
- version = "1.0.41"
7
+ version = "1.0.42"
8
8
  description = "A Comprehensive Tool for Setting Up Virtual Machines."
9
9
  readme = "README.md"
10
10
  authors = [
@@ -76,7 +76,7 @@ include = '\.pyi?$'
76
76
  profile = "black"
77
77
  multi_line_output = 3
78
78
  [tool.bumpversion]
79
- current_version = "1.0.41"
79
+ current_version = "1.0.42"
80
80
  commit = true
81
81
  tag = true
82
82
 
@@ -12,7 +12,7 @@ else:
12
12
 
13
13
  setup(
14
14
  name="vm_tool",
15
- version="1.0.41", # This will be updated by bump2version
15
+ version="1.0.42", # This will be updated by bump2version
16
16
  packages=find_packages(),
17
17
  description="A Comprehensive Tool for Setting Up Virtual Machines.",
18
18
  long_description=long_description,
@@ -6,7 +6,7 @@ def main():
6
6
  parser = argparse.ArgumentParser(
7
7
  description="VM Tool: Setup, Provision, and Manage VMs"
8
8
  )
9
- parser.add_argument("--version", action="version", version="1.0.41")
9
+ parser.add_argument("--version", action="version", version="1.0.42")
10
10
  parser.add_argument(
11
11
  "--verbose", "-v", action="store_true", help="Enable verbose output"
12
12
  )
@@ -168,6 +168,29 @@ def main():
168
168
  "--inventory", type=str, default="inventory.yml", help="Inventory file to use"
169
169
  )
170
170
 
171
+ # Hydrate Env command
172
+ hydrate_parser = subparsers.add_parser(
173
+ "hydrate-env", help="Hydrate missing env files from secrets"
174
+ )
175
+ hydrate_parser.add_argument(
176
+ "--compose-file",
177
+ type=str,
178
+ default="docker-compose.yml",
179
+ help="Path to docker-compose.yml",
180
+ )
181
+ hydrate_parser.add_argument(
182
+ "--secrets",
183
+ type=str,
184
+ required=True,
185
+ help="JSON string of GitHub secrets",
186
+ )
187
+ hydrate_parser.add_argument(
188
+ "--project-root",
189
+ type=str,
190
+ default=".",
191
+ help="Project root directory",
192
+ )
193
+
171
194
  # Docker Deploy command
172
195
  docker_parser = subparsers.add_parser(
173
196
  "deploy-docker", help="Deploy using Docker Compose"
@@ -637,6 +660,25 @@ def main():
637
660
  print(f"Error: {e}")
638
661
  sys.exit(1)
639
662
 
663
+ elif args.command == "hydrate-env":
664
+ try:
665
+ import json
666
+ from vm_tool.runner import SetupRunner, SetupRunnerConfig
667
+
668
+ secrets_map = json.loads(args.secrets)
669
+ config = SetupRunnerConfig(github_project_url="dummy")
670
+ runner = SetupRunner(config)
671
+
672
+ print("💧 Hydrating environment files from secrets...")
673
+ runner.hydrate_env_from_secrets(
674
+ compose_file=args.compose_file,
675
+ secrets_map=secrets_map,
676
+ project_root=args.project_root,
677
+ )
678
+ except Exception as e:
679
+ print(f"❌ Failed to hydrate env: {e}")
680
+ sys.exit(1)
681
+
640
682
  elif args.command == "completion":
641
683
  from vm_tool.completion import print_completion, install_completion
642
684
 
@@ -171,6 +171,75 @@ class SetupRunner:
171
171
  self.env_path = config.env_path
172
172
  self.env_data = config.env_data
173
173
 
174
+ def _get_compose_dependencies(self, compose_file: str) -> List[dict]:
175
+ """
176
+ Parses docker-compose file to find local file dependencies (env_files, volumes).
177
+ Returns a list of dicts: {'src': 'local/path', 'dest': 'remote/path'}
178
+ """
179
+ dependencies = []
180
+ if not os.path.exists(compose_file):
181
+ return dependencies
182
+
183
+ try:
184
+ with open(compose_file, "r") as f:
185
+ data = yaml.safe_load(f)
186
+
187
+ if not data or "services" not in data:
188
+ return dependencies
189
+
190
+ found_paths = set()
191
+
192
+ for service in data.get("services", {}).values():
193
+ # Check env_file
194
+ env_files = service.get("env_file", [])
195
+ if isinstance(env_files, str):
196
+ env_files = [env_files]
197
+
198
+ for env_path in env_files:
199
+ # Normalize local path
200
+ if env_path.startswith("./"):
201
+ clean_path = env_path[2:]
202
+ else:
203
+ clean_path = env_path
204
+
205
+ # Only include relative paths that are files
206
+ if not clean_path.startswith("/") and os.path.exists(clean_path):
207
+ if clean_path not in found_paths:
208
+ found_paths.add(clean_path)
209
+ dependencies.append({"src": clean_path, "dest": clean_path})
210
+ elif not os.path.exists(clean_path):
211
+ logger.warning(
212
+ f"⚠️ Referenced env_file not found locally: {clean_path}"
213
+ )
214
+
215
+ # Check volumes (bind mounts)
216
+ volumes = service.get("volumes", [])
217
+ for vol in volumes:
218
+ if isinstance(vol, str):
219
+ parts = vol.split(":")
220
+ if len(parts) >= 2:
221
+ host_path = parts[0]
222
+ # Check if it's a relative path bind mount
223
+ if (
224
+ host_path.startswith("./")
225
+ or host_path.startswith("../")
226
+ ) and os.path.exists(host_path):
227
+ if host_path.startswith("./"):
228
+ clean_path = host_path[2:]
229
+ else:
230
+ clean_path = host_path
231
+
232
+ if clean_path not in found_paths:
233
+ found_paths.add(clean_path)
234
+ dependencies.append(
235
+ {"src": clean_path, "dest": clean_path}
236
+ )
237
+
238
+ except Exception as e:
239
+ logger.warning(f"Failed to parse compose file for dependencies: {e}")
240
+
241
+ return dependencies
242
+
174
243
  def _get_git_commit(self) -> Optional[str]:
175
244
  """Get current git commit hash if in a git repository."""
176
245
  import subprocess
@@ -225,6 +294,65 @@ class SetupRunner:
225
294
  f"An error occurred while running the Ansible playbook: {str(e)}"
226
295
  )
227
296
 
297
+ def hydrate_env_from_secrets(
298
+ self, compose_file: str, secrets_map: dict, project_root: str = "."
299
+ ):
300
+ """
301
+ Scans compose file for env_files. If a file is missing locally,
302
+ checks secrets_map for a matching key (FILENAME_EXT -> FILENAME_EXT output as SNAKE_CASE)
303
+ and creates the file.
304
+ Example: env/backend.env -> checks secrets_map['BACKEND_ENV']
305
+ """
306
+ dependencies = self._get_compose_dependencies(compose_file)
307
+
308
+ # We need to find *potential* dependencies that might not exist yet.
309
+ # _get_compose_dependencies only returns existing ones.
310
+ # So we need to parse again broadly or just rely on what we find.
311
+ # Actually, _get_compose_dependencies skips missing files.
312
+ # So we should parse manually here to find *missing* ones.
313
+
314
+ try:
315
+ with open(compose_file, "r") as f:
316
+ data = yaml.safe_load(f)
317
+
318
+ if not data or "services" not in data:
319
+ return
320
+
321
+ for service in data.get("services", {}).values():
322
+ env_files = service.get("env_file", [])
323
+ if isinstance(env_files, str):
324
+ env_files = [env_files]
325
+
326
+ for env_path in env_files:
327
+ # Resolve path relative to project root
328
+ full_path = os.path.join(project_root, env_path)
329
+
330
+ if not os.path.exists(full_path):
331
+ # Attempt to hydrate
332
+ filename = os.path.basename(env_path)
333
+ # Normalize keys: backend.env -> BACKEND_ENV
334
+ secret_key = filename.replace(".", "_").upper()
335
+
336
+ secret_value = secrets_map.get(secret_key)
337
+ if secret_value:
338
+ logger.info(
339
+ f"💧 Hydrating {env_path} from secret {secret_key}"
340
+ )
341
+ # Ensure directory exists
342
+ os.makedirs(os.path.dirname(full_path), exist_ok=True)
343
+ with open(full_path, "w") as out:
344
+ out.write(secret_value)
345
+ else:
346
+ logger.warning(
347
+ f"⚠️ Missing env file {env_path} and no secret found for {secret_key}"
348
+ )
349
+ else:
350
+ logger.debug(f"✅ Env file exists: {env_path}")
351
+
352
+ except Exception as e:
353
+ logger.error(f"Failed to hydrate env files: {e}")
354
+ raise
355
+
228
356
  def run_setup(self):
229
357
  """Runs the setup process using Ansible."""
230
358
  extravars = {
@@ -402,6 +530,24 @@ class SetupRunner:
402
530
  if deploy_command:
403
531
  extravars["DEPLOY_COMMAND"] = deploy_command
404
532
 
533
+ # Dynamic Dependency Detection
534
+ dependencies = self._get_compose_dependencies(compose_file)
535
+
536
+ # Ensure CLI-provided env_file is included in detection logic
537
+ if env_file:
538
+ # Normalize and check existence
539
+ clean_env_path = env_file[2:] if env_file.startswith("./") else env_file
540
+ if os.path.exists(clean_env_path):
541
+ # Check if already in dependencies
542
+ if not any(d["src"] == clean_env_path for d in dependencies):
543
+ dependencies.append({"src": clean_env_path, "dest": clean_env_path})
544
+
545
+ if dependencies:
546
+ logger.info(
547
+ f"📦 Detected dependencies to copy: {[d['src'] for d in dependencies]}"
548
+ )
549
+ extravars["FILES_TO_COPY"] = dependencies
550
+
405
551
  playbook_path = os.path.join(
406
552
  os.path.dirname(__file__), "vm_setup", "push_code.yml"
407
553
  )
@@ -31,10 +31,35 @@
31
31
  src: "{{ SOURCE_PATH }}/{{ DOCKER_COMPOSE_FILE_PATH }}"
32
32
  dest: "{{ project_dest_dir }}/{{ DOCKER_COMPOSE_FILE_PATH }}"
33
33
 
34
+ # Handle dynamic dependencies (new method)
35
+ - name: Ensure parent directories for dependencies exist
36
+ file:
37
+ path: "{{ project_dest_dir }}/{{ item.dest | dirname }}"
38
+ state: directory
39
+ mode: '0755'
40
+ loop: "{{ FILES_TO_COPY | default([]) }}"
41
+ when: FILES_TO_COPY is defined and (item.dest | dirname) != ''
42
+
43
+ - name: Copy dependency files
44
+ copy:
45
+ src: "{{ SOURCE_PATH }}/{{ item.src }}"
46
+ dest: "{{ project_dest_dir }}/{{ item.dest }}"
47
+ loop: "{{ FILES_TO_COPY | default([]) }}"
48
+ when: FILES_TO_COPY is defined
49
+
50
+ # Backward compatibility for single env file
51
+ - name: Ensure Env file parent directory exists
52
+ file:
53
+ path: "{{ project_dest_dir }}/{{ ENV_FILE_PATH | default('.env') | dirname }}"
54
+ state: directory
55
+ mode: '0755'
56
+ when: FILES_TO_COPY is not defined and ENV_FILE_PATH is defined and (ENV_FILE_PATH | dirname) != ''
57
+
34
58
  - name: Copy Env file
35
59
  copy:
36
60
  src: "{{ SOURCE_PATH }}/{{ ENV_FILE_PATH | default('.env') }}"
37
61
  dest: "{{ project_dest_dir }}/{{ ENV_FILE_PATH | default('.env') }}"
62
+ when: FILES_TO_COPY is not defined
38
63
  failed_when: false
39
64
 
40
65
  - name: Deploy application
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vm_tool
3
- Version: 1.0.41
3
+ Version: 1.0.42
4
4
  Summary: A Comprehensive Tool for Setting Up Virtual Machines.
5
5
  Home-page: https://github.com/thesunnysinha/vm_tool
6
6
  Author: Sunny Sinha
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes