clonebox 0.1.28__tar.gz → 0.1.30__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 (34) hide show
  1. {clonebox-0.1.28/src/clonebox.egg-info → clonebox-0.1.30}/PKG-INFO +3 -1
  2. {clonebox-0.1.28 → clonebox-0.1.30}/pyproject.toml +3 -1
  3. {clonebox-0.1.28 → clonebox-0.1.30/src/clonebox.egg-info}/PKG-INFO +3 -1
  4. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox.egg-info/requires.txt +2 -0
  5. {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_coverage_boost_final.py +43 -9
  6. {clonebox-0.1.28 → clonebox-0.1.30}/LICENSE +0 -0
  7. {clonebox-0.1.28 → clonebox-0.1.30}/README.md +0 -0
  8. {clonebox-0.1.28 → clonebox-0.1.30}/setup.cfg +0 -0
  9. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/__init__.py +0 -0
  10. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/__main__.py +0 -0
  11. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/cli.py +0 -0
  12. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/cloner.py +0 -0
  13. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/container.py +0 -0
  14. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/dashboard.py +0 -0
  15. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/detector.py +0 -0
  16. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/models.py +0 -0
  17. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/profiles.py +0 -0
  18. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/templates/profiles/ml-dev.yaml +0 -0
  19. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/validator.py +0 -0
  20. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox.egg-info/SOURCES.txt +0 -0
  21. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox.egg-info/dependency_links.txt +0 -0
  22. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox.egg-info/entry_points.txt +0 -0
  23. {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox.egg-info/top_level.txt +0 -0
  24. {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_cli.py +0 -0
  25. {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_cloner.py +0 -0
  26. {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_cloner_simple.py +0 -0
  27. {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_container.py +0 -0
  28. {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_coverage_additional.py +0 -0
  29. {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_dashboard_coverage.py +0 -0
  30. {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_detector.py +0 -0
  31. {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_models.py +0 -0
  32. {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_network.py +0 -0
  33. {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_profiles.py +0 -0
  34. {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clonebox
3
- Version: 0.1.28
3
+ Version: 0.1.30
4
4
  Summary: Clone your workstation environment to an isolated VM with selective apps, paths and services
5
5
  Author: CloneBox Team
6
6
  License: Apache-2.0
@@ -42,6 +42,8 @@ Provides-Extra: test
42
42
  Requires-Dist: pytest>=7.0.0; extra == "test"
43
43
  Requires-Dist: pytest-cov>=4.0.0; extra == "test"
44
44
  Requires-Dist: pytest-timeout>=2.0.0; extra == "test"
45
+ Requires-Dist: pytest-asyncio; extra == "test"
46
+ Requires-Dist: fastapi>=0.100.0; extra == "test"
45
47
  Provides-Extra: dashboard
46
48
  Requires-Dist: fastapi>=0.100.0; extra == "dashboard"
47
49
  Requires-Dist: uvicorn>=0.22.0; extra == "dashboard"
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "clonebox"
7
- version = "0.1.28"
7
+ version = "0.1.30"
8
8
  description = "Clone your workstation environment to an isolated VM with selective apps, paths and services"
9
9
  readme = "README.md"
10
10
  license = {text = "Apache-2.0"}
@@ -52,6 +52,8 @@ test = [
52
52
  "pytest>=7.0.0",
53
53
  "pytest-cov>=4.0.0",
54
54
  "pytest-timeout>=2.0.0",
55
+ "pytest-asyncio",
56
+ "fastapi>=0.100.0",
55
57
  ]
56
58
  dashboard = [
57
59
  "fastapi>=0.100.0",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clonebox
3
- Version: 0.1.28
3
+ Version: 0.1.30
4
4
  Summary: Clone your workstation environment to an isolated VM with selective apps, paths and services
5
5
  Author: CloneBox Team
6
6
  License: Apache-2.0
@@ -42,6 +42,8 @@ Provides-Extra: test
42
42
  Requires-Dist: pytest>=7.0.0; extra == "test"
43
43
  Requires-Dist: pytest-cov>=4.0.0; extra == "test"
44
44
  Requires-Dist: pytest-timeout>=2.0.0; extra == "test"
45
+ Requires-Dist: pytest-asyncio; extra == "test"
46
+ Requires-Dist: fastapi>=0.100.0; extra == "test"
45
47
  Provides-Extra: dashboard
46
48
  Requires-Dist: fastapi>=0.100.0; extra == "dashboard"
47
49
  Requires-Dist: uvicorn>=0.22.0; extra == "dashboard"
@@ -21,3 +21,5 @@ mypy>=1.0.0
21
21
  pytest>=7.0.0
22
22
  pytest-cov>=4.0.0
23
23
  pytest-timeout>=2.0.0
24
+ pytest-asyncio
25
+ fastapi>=0.100.0
@@ -13,24 +13,40 @@ from clonebox.cloner import SelectiveVMCloner, VMConfig
13
13
 
14
14
 
15
15
  class ValidatorResponder:
16
+ def __init__(self, fail_all=False):
17
+ self.fail_all = fail_all
18
+
16
19
  def __call__(self, cmd, timeout=10):
20
+ if self.fail_all:
21
+ return None
17
22
  if "mount | grep 9p" in cmd:
18
23
  return "/dev/host on /mnt/guest type 9p (rw)\n/dev/host on /home/ubuntu/.config/google-chrome type 9p (rw)"
19
24
  if "test -d" in cmd:
20
25
  return "yes"
21
26
  if "ls -A" in cmd:
22
- return "5"
27
+ if "wc -l" in cmd:
28
+ return "5"
29
+ return "file1 file2"
23
30
  if "dpkg -l" in cmd:
31
+ # Matches '^ii {package}' | awk '{{print $3}}'
32
+ if "awk" in cmd:
33
+ return "1.0-all"
24
34
  return "ii package 1.0 all"
25
35
  if "systemctl is-enabled" in cmd:
26
36
  return "enabled"
27
37
  if "systemctl is-active" in cmd:
28
38
  return "active"
29
39
  if "systemctl show -p MainPID" in cmd:
40
+ if "--value" in cmd:
41
+ return "1234"
30
42
  return "MainPID=1234"
31
43
  if "snap list" in cmd:
44
+ if "awk" in cmd:
45
+ return "1.0"
32
46
  return "package 1.0"
33
47
  if "snap connections" in cmd:
48
+ if "awk" in cmd:
49
+ return "desktop slot\nhome slot\nnetwork slot"
34
50
  return "content-interface package:plug package:slot"
35
51
  if "pgrep" in cmd:
36
52
  return "5678"
@@ -43,21 +59,22 @@ class ValidatorResponder:
43
59
  # Add responders for more branches in validator.py
44
60
  if "snap logs" in cmd:
45
61
  return "some snap logs content"
46
- if "firefox --headless" in cmd or "chromium --headless" in cmd:
62
+ if "firefox --headless" in cmd or "chromium --headless" in cmd or "google-chrome --headless" in cmd:
47
63
  return "SUCCESS"
48
64
  return ""
49
65
 
50
66
 
51
67
  def test_validator_comprehensive_coverage(monkeypatch):
52
68
  config = {
69
+ "vm": {"username": "ubuntu"},
53
70
  "paths": {"/host/path": "/mnt/guest"},
54
- "packages": ["vim"],
55
- "services": ["docker"],
56
- "snap_packages": ["chromium"],
71
+ "packages": ["vim", "firefox"],
72
+ "services": ["docker", "nginx", "libvirtd"],
73
+ "snap_packages": ["chromium", "pycharm-community", "firefox", "code"],
57
74
  "app_data_paths": {"/host/chrome": "/home/ubuntu/.config/google-chrome"},
58
75
  "smoke_test": True,
59
76
  }
60
- v = VMValidator(config, "test-vm", "qemu:///system", None)
77
+ v = VMValidator(config, "test-vm", "qemu:///system", None, require_running_apps=True)
61
78
  monkeypatch.setattr(v, "_exec_in_vm", ValidatorResponder())
62
79
 
63
80
  # Run all validation methods to cover branches
@@ -73,11 +90,25 @@ def test_validator_comprehensive_coverage(monkeypatch):
73
90
  v.validate_all()
74
91
 
75
92
  # Test error cases in validator methods by forcing exceptions or empty responses
76
- monkeypatch.setattr(v, "_exec_in_vm", lambda c, timeout=10: "")
93
+ monkeypatch.setattr(v, "_exec_in_vm", lambda c, timeout=10: None)
77
94
  v.validate_mounts()
78
95
  v.validate_packages()
96
+ v.validate_snap_packages()
79
97
  v.validate_services()
80
98
  v.validate_apps()
99
+ v.validate_smoke_tests()
100
+
101
+ v.require_running_apps = False
102
+ v.validate_apps()
103
+
104
+ # Test pgrep pattern edge cases
105
+ def mock_pgrep(cmd, timeout=10):
106
+ if "pgrep" in cmd:
107
+ return "1234"
108
+ return "yes"
109
+
110
+ monkeypatch.setattr(v, "_exec_in_vm", mock_pgrep)
111
+ v.validate_apps()
81
112
 
82
113
 
83
114
  # --- Cloner Mocking ---
@@ -246,8 +277,11 @@ def test_cloner_cloudinit_generation():
246
277
 
247
278
  with tempfile.TemporaryDirectory() as tmpdir:
248
279
  vm_dir = Path(tmpdir)
249
- # Mock Path.exists for the host path in config.paths
250
- with patch("pathlib.Path.exists", return_value=True):
280
+ # Mock Path.exists for the host path in config.paths and subprocess for genisoimage
281
+ with patch("pathlib.Path.exists", return_value=True), patch(
282
+ "subprocess.run"
283
+ ) as mock_run:
284
+ mock_run.return_value = Mock(returncode=0)
251
285
  iso_path = cloner._create_cloudinit_iso(vm_dir, config)
252
286
  assert iso_path is not None
253
287
  assert (vm_dir / "cloud-init" / "user-data").exists()
File without changes
File without changes
File without changes
File without changes
File without changes