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.
- {clonebox-0.1.28/src/clonebox.egg-info → clonebox-0.1.30}/PKG-INFO +3 -1
- {clonebox-0.1.28 → clonebox-0.1.30}/pyproject.toml +3 -1
- {clonebox-0.1.28 → clonebox-0.1.30/src/clonebox.egg-info}/PKG-INFO +3 -1
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox.egg-info/requires.txt +2 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_coverage_boost_final.py +43 -9
- {clonebox-0.1.28 → clonebox-0.1.30}/LICENSE +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/README.md +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/setup.cfg +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/__init__.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/__main__.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/cli.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/cloner.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/container.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/dashboard.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/detector.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/models.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/profiles.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/templates/profiles/ml-dev.yaml +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox/validator.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox.egg-info/SOURCES.txt +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox.egg-info/dependency_links.txt +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox.egg-info/entry_points.txt +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/src/clonebox.egg-info/top_level.txt +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_cli.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_cloner.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_cloner_simple.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_container.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_coverage_additional.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_dashboard_coverage.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_detector.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_models.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_network.py +0 -0
- {clonebox-0.1.28 → clonebox-0.1.30}/tests/test_profiles.py +0 -0
- {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.
|
|
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.
|
|
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.
|
|
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"
|
|
@@ -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
|
-
|
|
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
|
|
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
|