cyclo-manager 0.2.0.dev1__tar.gz → 0.2.0.dev3__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.
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/PKG-INFO +1 -1
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_host_agent/routers/repos.py +13 -17
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_manager.egg-info/PKG-INFO +1 -1
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_manager_cli/cli.py +65 -19
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/pyproject.toml +1 -1
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/setup.cfg +1 -1
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/README.md +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_host_agent/__init__.py +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_host_agent/main.py +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_host_agent/models.py +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_host_agent/routers/__init__.py +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_host_agent/routers/update.py +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_manager.egg-info/SOURCES.txt +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_manager.egg-info/dependency_links.txt +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_manager.egg-info/entry_points.txt +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_manager.egg-info/requires.txt +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_manager.egg-info/top_level.txt +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_manager_cli/__init__.py +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_manager_cli/config/config.yml +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_manager_cli/docker/docker-compose.yml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cyclo-manager
|
|
3
|
-
Version: 0.2.0.
|
|
3
|
+
Version: 0.2.0.dev3
|
|
4
4
|
Summary: cyclo_manager CLI: pip-installable launcher for cyclo_manager server and UI containers. Run 'cyclo_manager up' to start Docker stack.
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -22,7 +22,6 @@ import asyncio
|
|
|
22
22
|
import json
|
|
23
23
|
import os
|
|
24
24
|
import re
|
|
25
|
-
import subprocess
|
|
26
25
|
import urllib.request
|
|
27
26
|
from pathlib import Path
|
|
28
27
|
from typing import Optional
|
|
@@ -87,23 +86,20 @@ def _fmt_cmd(cmd: str, output: str) -> str:
|
|
|
87
86
|
|
|
88
87
|
# ── git helpers ────────────────────────────────────────────────────────────────
|
|
89
88
|
|
|
90
|
-
def _git_sync(args: list[str], cwd: Optional[Path] = None) -> tuple[int, str, str]:
|
|
91
|
-
try:
|
|
92
|
-
result = subprocess.run(
|
|
93
|
-
['git', *args],
|
|
94
|
-
cwd=str(cwd) if cwd else None,
|
|
95
|
-
capture_output=True,
|
|
96
|
-
timeout=GIT_TIMEOUT,
|
|
97
|
-
)
|
|
98
|
-
return result.returncode, result.stdout.decode(), result.stderr.decode()
|
|
99
|
-
except subprocess.TimeoutExpired:
|
|
100
|
-
return 1, '', 'git timed out'
|
|
101
|
-
except Exception as e:
|
|
102
|
-
return 1, '', str(e)
|
|
103
|
-
|
|
104
|
-
|
|
105
89
|
async def _git(args: list[str], cwd: Optional[Path] = None) -> tuple[int, str, str]:
|
|
106
|
-
|
|
90
|
+
proc = await asyncio.create_subprocess_exec(
|
|
91
|
+
'git', *args,
|
|
92
|
+
cwd=str(cwd) if cwd else None,
|
|
93
|
+
stdout=asyncio.subprocess.PIPE,
|
|
94
|
+
stderr=asyncio.subprocess.PIPE,
|
|
95
|
+
)
|
|
96
|
+
try:
|
|
97
|
+
stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=GIT_TIMEOUT)
|
|
98
|
+
except asyncio.TimeoutError:
|
|
99
|
+
proc.kill()
|
|
100
|
+
await proc.wait()
|
|
101
|
+
raise
|
|
102
|
+
return proc.returncode, stdout.decode(), stderr.decode()
|
|
107
103
|
|
|
108
104
|
|
|
109
105
|
async def _repo_info(repo_path: Path) -> RepoInfo:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cyclo-manager
|
|
3
|
-
Version: 0.2.0.
|
|
3
|
+
Version: 0.2.0.dev3
|
|
4
4
|
Summary: cyclo_manager CLI: pip-installable launcher for cyclo_manager server and UI containers. Run 'cyclo_manager up' to start Docker stack.
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -33,6 +33,7 @@ import sys
|
|
|
33
33
|
PYPI_PACKAGE = 'cyclo-manager'
|
|
34
34
|
HOST_AGENT_SERVICE = 'cyclo_host_agent'
|
|
35
35
|
HOST_AGENT_SOCKET = '/var/run/robotis/agent_sockets/host/host_agent.sock'
|
|
36
|
+
HOST_AGENT_SOCKET_DIR = '/var/run/robotis/agent_sockets/host'
|
|
36
37
|
|
|
37
38
|
# `cyclo_manager up` starts these immediately.
|
|
38
39
|
COMPOSE_SERVICES_UP = ('cyclo_manager', 'ui')
|
|
@@ -53,24 +54,67 @@ def _packaged_config_path() -> Path:
|
|
|
53
54
|
return _config_dir() / 'config.yml'
|
|
54
55
|
|
|
55
56
|
|
|
56
|
-
def
|
|
57
|
-
"""
|
|
58
|
-
|
|
59
|
-
['systemctl', 'is-active', f'{HOST_AGENT_SERVICE}.service'],
|
|
60
|
-
capture_output=True,
|
|
61
|
-
text=True,
|
|
62
|
-
)
|
|
63
|
-
return result.returncode == 0
|
|
57
|
+
def _resolve_service_user() -> tuple[str, Path] | None:
|
|
58
|
+
"""
|
|
59
|
+
Return (username, home) for the host agent systemd service.
|
|
64
60
|
|
|
61
|
+
Uses SUDO_USER when cyclo_manager up is invoked via sudo so the agent runs
|
|
62
|
+
as the login user (required for git repo scans under ~/...).
|
|
63
|
+
"""
|
|
64
|
+
sudo_user = os.environ.get('SUDO_USER')
|
|
65
|
+
if sudo_user:
|
|
66
|
+
return sudo_user, Path(f'/home/{sudo_user}')
|
|
67
|
+
user = os.environ.get('USER') or os.getlogin()
|
|
68
|
+
if user == 'root':
|
|
69
|
+
print(
|
|
70
|
+
'Error: cyclo_manager up must run as a normal user (e.g. robotis), not root.',
|
|
71
|
+
file=sys.stderr,
|
|
72
|
+
)
|
|
73
|
+
return None
|
|
74
|
+
return user, Path.home()
|
|
65
75
|
|
|
66
76
|
|
|
67
|
-
def
|
|
77
|
+
def _setup_socket_dir(user: str) -> bool:
|
|
68
78
|
"""
|
|
69
|
-
|
|
79
|
+
Ensure the host agent UDS directory exists and is owned by the service user.
|
|
70
80
|
|
|
71
|
-
|
|
72
|
-
|
|
81
|
+
Only host/ is chowned so other agent sockets under agent_sockets/ are untouched.
|
|
82
|
+
Removes a stale socket file (e.g. left by a previous root-owned service).
|
|
73
83
|
"""
|
|
84
|
+
try:
|
|
85
|
+
subprocess.run(
|
|
86
|
+
['sudo', 'mkdir', '-p', HOST_AGENT_SOCKET_DIR],
|
|
87
|
+
check=True,
|
|
88
|
+
capture_output=True,
|
|
89
|
+
)
|
|
90
|
+
subprocess.run(
|
|
91
|
+
['sudo', 'chown', f'{user}:{user}', HOST_AGENT_SOCKET_DIR],
|
|
92
|
+
check=True,
|
|
93
|
+
capture_output=True,
|
|
94
|
+
)
|
|
95
|
+
subprocess.run(
|
|
96
|
+
['sudo', 'rm', '-f', HOST_AGENT_SOCKET],
|
|
97
|
+
check=True,
|
|
98
|
+
capture_output=True,
|
|
99
|
+
)
|
|
100
|
+
return True
|
|
101
|
+
except subprocess.CalledProcessError as e:
|
|
102
|
+
print(f'Failed to set up host agent socket directory: {e}', file=sys.stderr)
|
|
103
|
+
return False
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _ensure_host_agent() -> int:
|
|
107
|
+
"""
|
|
108
|
+
Install or refresh cyclo_host_agent: systemd unit, socket dir, and service start.
|
|
109
|
+
|
|
110
|
+
Idempotent — safe to run on every `cyclo_manager up` (fixes upgraded units and
|
|
111
|
+
socket ownership after switching away from a root-owned service).
|
|
112
|
+
"""
|
|
113
|
+
account = _resolve_service_user()
|
|
114
|
+
if account is None:
|
|
115
|
+
return 1
|
|
116
|
+
|
|
117
|
+
user, user_home = account
|
|
74
118
|
agent_exe = shutil.which('cyclo_host_agent')
|
|
75
119
|
if not agent_exe:
|
|
76
120
|
print(
|
|
@@ -80,8 +124,9 @@ def _create_host_agent() -> int:
|
|
|
80
124
|
)
|
|
81
125
|
return 1
|
|
82
126
|
|
|
83
|
-
|
|
84
|
-
|
|
127
|
+
if not _setup_socket_dir(user):
|
|
128
|
+
return 1
|
|
129
|
+
|
|
85
130
|
service_content = f"""\
|
|
86
131
|
[Unit]
|
|
87
132
|
Description=Cyclo Host Agent
|
|
@@ -89,7 +134,8 @@ After=network.target
|
|
|
89
134
|
|
|
90
135
|
[Service]
|
|
91
136
|
Type=simple
|
|
92
|
-
User={
|
|
137
|
+
User={user}
|
|
138
|
+
Group={user}
|
|
93
139
|
ExecStart={agent_exe}
|
|
94
140
|
Environment=HOME={user_home}
|
|
95
141
|
Restart=always
|
|
@@ -110,7 +156,8 @@ WantedBy=multi-user.target
|
|
|
110
156
|
check=True,
|
|
111
157
|
)
|
|
112
158
|
subprocess.run(['sudo', 'systemctl', 'daemon-reload'], check=True)
|
|
113
|
-
subprocess.run(['sudo', 'systemctl', 'enable',
|
|
159
|
+
subprocess.run(['sudo', 'systemctl', 'enable', f'{HOST_AGENT_SERVICE}.service'], check=True)
|
|
160
|
+
subprocess.run(['sudo', 'systemctl', 'restart', f'{HOST_AGENT_SERVICE}.service'], check=True)
|
|
114
161
|
print('Host agent service installed and started.')
|
|
115
162
|
return 0
|
|
116
163
|
except subprocess.CalledProcessError as e:
|
|
@@ -123,9 +170,8 @@ WantedBy=multi-user.target
|
|
|
123
170
|
|
|
124
171
|
def cmd_up(args: argparse.Namespace) -> int:
|
|
125
172
|
"""Start API + UI; create zenoh and noVNC containers without starting them."""
|
|
126
|
-
if
|
|
127
|
-
|
|
128
|
-
print('Warning: Failed to install host agent service.')
|
|
173
|
+
if _ensure_host_agent() != 0:
|
|
174
|
+
print('Warning: Failed to install host agent service.', file=sys.stderr)
|
|
129
175
|
|
|
130
176
|
config_path = _packaged_config_path()
|
|
131
177
|
if not config_path.is_file():
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cyclo-manager"
|
|
7
|
-
version = "0.2.0.
|
|
7
|
+
version = "0.2.0.dev3"
|
|
8
8
|
description = "cyclo_manager CLI: pip-installable launcher for cyclo_manager server and UI containers. Run 'cyclo_manager up' to start Docker stack."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_manager.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_manager.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev3}/cyclo_manager_cli/docker/docker-compose.yml
RENAMED
|
File without changes
|