cyclo-manager 1.2.1.dev0__tar.gz → 1.2.2.dev0__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 (23) hide show
  1. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/PKG-INFO +14 -6
  2. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/README.md +13 -5
  3. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_manager.egg-info/PKG-INFO +14 -6
  4. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_manager_cli/__init__.py +1 -1
  5. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_manager_cli/cli.py +87 -31
  6. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_manager_cli/docker/docker-compose.yml +2 -2
  7. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/pyproject.toml +1 -1
  8. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_host_agent/__init__.py +0 -0
  9. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_host_agent/cpu_usage.py +0 -0
  10. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_host_agent/main.py +0 -0
  11. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_host_agent/models.py +0 -0
  12. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_host_agent/routers/__init__.py +0 -0
  13. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_host_agent/routers/files.py +0 -0
  14. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_host_agent/routers/repos.py +0 -0
  15. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_host_agent/routers/system_stats.py +0 -0
  16. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_host_agent/routers/update.py +0 -0
  17. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_manager.egg-info/SOURCES.txt +0 -0
  18. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_manager.egg-info/dependency_links.txt +0 -0
  19. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_manager.egg-info/entry_points.txt +0 -0
  20. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_manager.egg-info/requires.txt +0 -0
  21. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_manager.egg-info/top_level.txt +0 -0
  22. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/cyclo_manager_cli/config/config.yml +0 -0
  23. {cyclo_manager-1.2.1.dev0 → cyclo_manager-1.2.2.dev0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cyclo-manager
3
- Version: 1.2.1.dev0
3
+ Version: 1.2.2.dev0
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
@@ -54,7 +54,7 @@ For the full monorepo (API source, UI source, dev compose), see the [repository
54
54
  - **Python 3.10+**
55
55
  - **systemd**: required for the managed `cyclo_host_agent.service`
56
56
  - **`sudo`** — required on normal-user hosts to install the host agent systemd unit, socket directory permissions, and sudoers rules
57
- - For **`cyclo_manager update`:** **`pip`** or **`pip3`** on `PATH`
57
+ - For **`cyclo_manager update`:** **`pip`** in the Python environment running the CLI/host agent
58
58
  - **Root shell handling** — `cyclo_manager up` rejects direct root execution when a normal login user exists. On root-only devices, the host agent is installed as root.
59
59
  - **Agent sockets** on the host under `/var/run/robotis/agent_sockets/` (robot containers and host agent). The bundled Compose file bind-mounts this tree into the API container as `/agents/`.
60
60
 
@@ -91,13 +91,21 @@ python3 -m cyclo_manager_cli.cli up
91
91
  | `cyclo_manager up` | Install/refresh **cyclo_host_agent** (systemd unit, socket dir, sudoers), then `docker compose up -d` for **API + UI**, then `docker compose create --no-recreate` for **Zenoh** and **noVNC** (created but **not started**). Sets **`CYCLO_MANAGER_CONFIG_FILE`** to the bundled config. |
92
92
  | `cyclo_manager up --pull` | `docker compose pull` first, then the same as `up`. |
93
93
  | `cyclo_manager down` | **Tear down host agent** (stop/disable service, remove unit, sudoers, socket dir), then `docker compose down` for all services in the bundled compose file. |
94
- | `cyclo_manager update` | `docker compose down` (containers only — **host agent stays installed**), `pip install -U cyclo-manager`, **`docker compose pull`**, then `docker compose up` + create optional services, then **refresh host agent** (unit, socket, sudoers). |
94
+ | `cyclo_manager update` | Update the package and pull images before restarting the Docker stack and refreshing the host agent. |
95
95
  | `cyclo_manager update --no-pull` | Same as `update`, but skip image pull (use locally cached images). |
96
96
  | `cyclo_manager --help` | Subcommand overview |
97
97
 
98
98
  The CLI also has an internal `refresh-host-agent` subcommand. It is used by the sudoers rule and should normally not be invoked by users directly.
99
99
 
100
- **`down` vs `update`:** `down` removes the host agent entirely. `update` only stops Docker containers, upgrades the pip package, restarts the stack, and refreshes the host agent — it does **not** call `cyclo_manager down`.
100
+ **`down` vs `update`:** `down` removes the host agent entirely. `update` prepares the package and images, restarts the Docker stack, and refreshes the host agent — it does **not** call `cyclo_manager down`.
101
+
102
+ Updates use the running Python's pip and add `--break-system-packages` only when
103
+ required and supported. Package installation or image download failures leave
104
+ existing containers running; package changes are not automatically rolled back.
105
+
106
+ **Older installations:** once this fix is released, manually upgrade the package
107
+ once using your installation's Python, then run `cyclo_manager up --pull`.
108
+ Add `--break-system-packages` to the pip command only if pip requests it.
101
109
 
102
110
  ---
103
111
 
@@ -152,8 +160,8 @@ Defined in [`cyclo_manager_cli/docker/docker-compose.yml`](cyclo_manager_cli/doc
152
160
 
153
161
  | Compose service | Container name | `cyclo_manager up` | Image in this checkout |
154
162
  |-----------------|----------------|--------------------|-----------------|
155
- | `cyclo_manager` | `cyclo_manager` | **Started** | `robotis/cyclo-manager:1.2.1` |
156
- | `ui` | `cyclo_manager_ui` | **Started** | `robotis/cyclo-manager-ui:1.2.1` |
163
+ | `cyclo_manager` | `cyclo_manager` | **Started** | `robotis/cyclo-manager:1.2.2` |
164
+ | `ui` | `cyclo_manager_ui` | **Started** | `robotis/cyclo-manager-ui:1.2.2` |
157
165
  | `rmw_zenoh` | `zenoh_daemon` | **Created only** | `robotis/zenoh-daemon:latest` |
158
166
  | `novnc-server` | `novnc-server` | **Created only** | `robotis/novnc-server:latest` |
159
167
 
@@ -41,7 +41,7 @@ For the full monorepo (API source, UI source, dev compose), see the [repository
41
41
  - **Python 3.10+**
42
42
  - **systemd**: required for the managed `cyclo_host_agent.service`
43
43
  - **`sudo`** — required on normal-user hosts to install the host agent systemd unit, socket directory permissions, and sudoers rules
44
- - For **`cyclo_manager update`:** **`pip`** or **`pip3`** on `PATH`
44
+ - For **`cyclo_manager update`:** **`pip`** in the Python environment running the CLI/host agent
45
45
  - **Root shell handling** — `cyclo_manager up` rejects direct root execution when a normal login user exists. On root-only devices, the host agent is installed as root.
46
46
  - **Agent sockets** on the host under `/var/run/robotis/agent_sockets/` (robot containers and host agent). The bundled Compose file bind-mounts this tree into the API container as `/agents/`.
47
47
 
@@ -78,13 +78,21 @@ python3 -m cyclo_manager_cli.cli up
78
78
  | `cyclo_manager up` | Install/refresh **cyclo_host_agent** (systemd unit, socket dir, sudoers), then `docker compose up -d` for **API + UI**, then `docker compose create --no-recreate` for **Zenoh** and **noVNC** (created but **not started**). Sets **`CYCLO_MANAGER_CONFIG_FILE`** to the bundled config. |
79
79
  | `cyclo_manager up --pull` | `docker compose pull` first, then the same as `up`. |
80
80
  | `cyclo_manager down` | **Tear down host agent** (stop/disable service, remove unit, sudoers, socket dir), then `docker compose down` for all services in the bundled compose file. |
81
- | `cyclo_manager update` | `docker compose down` (containers only — **host agent stays installed**), `pip install -U cyclo-manager`, **`docker compose pull`**, then `docker compose up` + create optional services, then **refresh host agent** (unit, socket, sudoers). |
81
+ | `cyclo_manager update` | Update the package and pull images before restarting the Docker stack and refreshing the host agent. |
82
82
  | `cyclo_manager update --no-pull` | Same as `update`, but skip image pull (use locally cached images). |
83
83
  | `cyclo_manager --help` | Subcommand overview |
84
84
 
85
85
  The CLI also has an internal `refresh-host-agent` subcommand. It is used by the sudoers rule and should normally not be invoked by users directly.
86
86
 
87
- **`down` vs `update`:** `down` removes the host agent entirely. `update` only stops Docker containers, upgrades the pip package, restarts the stack, and refreshes the host agent — it does **not** call `cyclo_manager down`.
87
+ **`down` vs `update`:** `down` removes the host agent entirely. `update` prepares the package and images, restarts the Docker stack, and refreshes the host agent — it does **not** call `cyclo_manager down`.
88
+
89
+ Updates use the running Python's pip and add `--break-system-packages` only when
90
+ required and supported. Package installation or image download failures leave
91
+ existing containers running; package changes are not automatically rolled back.
92
+
93
+ **Older installations:** once this fix is released, manually upgrade the package
94
+ once using your installation's Python, then run `cyclo_manager up --pull`.
95
+ Add `--break-system-packages` to the pip command only if pip requests it.
88
96
 
89
97
  ---
90
98
 
@@ -139,8 +147,8 @@ Defined in [`cyclo_manager_cli/docker/docker-compose.yml`](cyclo_manager_cli/doc
139
147
 
140
148
  | Compose service | Container name | `cyclo_manager up` | Image in this checkout |
141
149
  |-----------------|----------------|--------------------|-----------------|
142
- | `cyclo_manager` | `cyclo_manager` | **Started** | `robotis/cyclo-manager:1.2.1` |
143
- | `ui` | `cyclo_manager_ui` | **Started** | `robotis/cyclo-manager-ui:1.2.1` |
150
+ | `cyclo_manager` | `cyclo_manager` | **Started** | `robotis/cyclo-manager:1.2.2` |
151
+ | `ui` | `cyclo_manager_ui` | **Started** | `robotis/cyclo-manager-ui:1.2.2` |
144
152
  | `rmw_zenoh` | `zenoh_daemon` | **Created only** | `robotis/zenoh-daemon:latest` |
145
153
  | `novnc-server` | `novnc-server` | **Created only** | `robotis/novnc-server:latest` |
146
154
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cyclo-manager
3
- Version: 1.2.1.dev0
3
+ Version: 1.2.2.dev0
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
@@ -54,7 +54,7 @@ For the full monorepo (API source, UI source, dev compose), see the [repository
54
54
  - **Python 3.10+**
55
55
  - **systemd**: required for the managed `cyclo_host_agent.service`
56
56
  - **`sudo`** — required on normal-user hosts to install the host agent systemd unit, socket directory permissions, and sudoers rules
57
- - For **`cyclo_manager update`:** **`pip`** or **`pip3`** on `PATH`
57
+ - For **`cyclo_manager update`:** **`pip`** in the Python environment running the CLI/host agent
58
58
  - **Root shell handling** — `cyclo_manager up` rejects direct root execution when a normal login user exists. On root-only devices, the host agent is installed as root.
59
59
  - **Agent sockets** on the host under `/var/run/robotis/agent_sockets/` (robot containers and host agent). The bundled Compose file bind-mounts this tree into the API container as `/agents/`.
60
60
 
@@ -91,13 +91,21 @@ python3 -m cyclo_manager_cli.cli up
91
91
  | `cyclo_manager up` | Install/refresh **cyclo_host_agent** (systemd unit, socket dir, sudoers), then `docker compose up -d` for **API + UI**, then `docker compose create --no-recreate` for **Zenoh** and **noVNC** (created but **not started**). Sets **`CYCLO_MANAGER_CONFIG_FILE`** to the bundled config. |
92
92
  | `cyclo_manager up --pull` | `docker compose pull` first, then the same as `up`. |
93
93
  | `cyclo_manager down` | **Tear down host agent** (stop/disable service, remove unit, sudoers, socket dir), then `docker compose down` for all services in the bundled compose file. |
94
- | `cyclo_manager update` | `docker compose down` (containers only — **host agent stays installed**), `pip install -U cyclo-manager`, **`docker compose pull`**, then `docker compose up` + create optional services, then **refresh host agent** (unit, socket, sudoers). |
94
+ | `cyclo_manager update` | Update the package and pull images before restarting the Docker stack and refreshing the host agent. |
95
95
  | `cyclo_manager update --no-pull` | Same as `update`, but skip image pull (use locally cached images). |
96
96
  | `cyclo_manager --help` | Subcommand overview |
97
97
 
98
98
  The CLI also has an internal `refresh-host-agent` subcommand. It is used by the sudoers rule and should normally not be invoked by users directly.
99
99
 
100
- **`down` vs `update`:** `down` removes the host agent entirely. `update` only stops Docker containers, upgrades the pip package, restarts the stack, and refreshes the host agent — it does **not** call `cyclo_manager down`.
100
+ **`down` vs `update`:** `down` removes the host agent entirely. `update` prepares the package and images, restarts the Docker stack, and refreshes the host agent — it does **not** call `cyclo_manager down`.
101
+
102
+ Updates use the running Python's pip and add `--break-system-packages` only when
103
+ required and supported. Package installation or image download failures leave
104
+ existing containers running; package changes are not automatically rolled back.
105
+
106
+ **Older installations:** once this fix is released, manually upgrade the package
107
+ once using your installation's Python, then run `cyclo_manager up --pull`.
108
+ Add `--break-system-packages` to the pip command only if pip requests it.
101
109
 
102
110
  ---
103
111
 
@@ -152,8 +160,8 @@ Defined in [`cyclo_manager_cli/docker/docker-compose.yml`](cyclo_manager_cli/doc
152
160
 
153
161
  | Compose service | Container name | `cyclo_manager up` | Image in this checkout |
154
162
  |-----------------|----------------|--------------------|-----------------|
155
- | `cyclo_manager` | `cyclo_manager` | **Started** | `robotis/cyclo-manager:1.2.1` |
156
- | `ui` | `cyclo_manager_ui` | **Started** | `robotis/cyclo-manager-ui:1.2.1` |
163
+ | `cyclo_manager` | `cyclo_manager` | **Started** | `robotis/cyclo-manager:1.2.2` |
164
+ | `ui` | `cyclo_manager_ui` | **Started** | `robotis/cyclo-manager-ui:1.2.2` |
157
165
  | `rmw_zenoh` | `zenoh_daemon` | **Created only** | `robotis/zenoh-daemon:latest` |
158
166
  | `novnc-server` | `novnc-server` | **Created only** | `robotis/novnc-server:latest` |
159
167
 
@@ -18,4 +18,4 @@
18
18
 
19
19
  """cyclo_manager CLI - pip-installable launcher for cyclo_manager server and UI containers."""
20
20
 
21
- __version__ = '1.2.1'
21
+ __version__ = '1.2.2.dev0'
@@ -31,6 +31,7 @@ import shutil
31
31
  import socket
32
32
  import subprocess
33
33
  import sys
34
+ import sysconfig
34
35
 
35
36
  PYPI_PACKAGE = 'cyclo-manager'
36
37
  HOST_AGENT_SERVICE = 'cyclo_host_agent'
@@ -443,54 +444,105 @@ def cmd_down(args: argparse.Namespace) -> int:
443
444
  return 0
444
445
 
445
446
 
446
- def cmd_update(args: argparse.Namespace) -> int:
447
- """Bring containers down, pip install -U, bring containers back up, restart host agent."""
448
- pip_exe = shutil.which('pip3') or shutil.which('pip')
449
- if not pip_exe:
450
- print('pip not found; cannot update package.', file=sys.stderr)
451
- return 1
447
+ def _package_update_command() -> list[str]:
448
+ """Use this interpreter's pip, overriding PEP 668 only when required and supported."""
449
+ if not sys.executable:
450
+ raise RuntimeError('Python executable is unknown; cannot update package.')
452
451
 
453
- compose_path = _docker_dir() / 'docker-compose.yml'
454
- if not compose_path.is_file():
455
- print(f'Compose file not found: {compose_path}', file=sys.stderr)
452
+ pip_command = [sys.executable, '-m', 'pip']
453
+ # Also checks that pip exists in this Python, without installing anything.
454
+ help_result = subprocess.run(
455
+ [*pip_command, 'install', '--help'],
456
+ check=True, capture_output=True, text=True, timeout=10,
457
+ )
458
+ command = [*pip_command, 'install', '-U', PYPI_PACKAGE]
459
+ in_venv = sys.prefix != sys.base_prefix or hasattr(sys, 'real_prefix')
460
+ marker = Path(sysconfig.get_path('stdlib')) / 'EXTERNALLY-MANAGED'
461
+ if not in_venv and marker.is_file():
462
+ if '--break-system-packages' not in help_result.stdout:
463
+ raise RuntimeError(
464
+ f'{sys.executable} is externally managed, but its pip does not support '
465
+ '--break-system-packages. Use a virtual environment or install a '
466
+ 'compatible pip through the OS package manager.'
467
+ )
468
+ command.append('--break-system-packages')
469
+ print('System Python is externally managed; using --break-system-packages.', flush=True)
470
+ else:
471
+ print('Using pip without --break-system-packages.', flush=True)
472
+ return command
473
+
474
+
475
+ def _updated_package_dir() -> Path:
476
+ """Resolve the installed package in a fresh Python after pip may have moved it."""
477
+ result = subprocess.run(
478
+ [sys.executable, '-c',
479
+ 'from pathlib import Path; import cyclo_manager_cli; '
480
+ 'print(Path(cyclo_manager_cli.__file__).resolve().parent)'],
481
+ check=True, capture_output=True, text=True, timeout=10,
482
+ )
483
+ package_dir = Path(result.stdout.strip())
484
+ if not package_dir.is_absolute():
485
+ raise RuntimeError('Cannot determine the updated package directory.')
486
+ return package_dir
487
+
488
+
489
+ def cmd_update(args: argparse.Namespace) -> int:
490
+ """Prepare the package and images before stopping containers and refreshing the agent."""
491
+ if not shutil.which('docker'):
492
+ print('Docker not found.', file=sys.stderr)
456
493
  return 1
457
- env = os.environ.copy()
458
- env['CYCLO_MANAGER_CONFIG_FILE'] = str(_packaged_config_path())
459
- env.setdefault('HOSTNAME', socket.gethostname())
460
- base = ['docker', 'compose', '-f', str(compose_path)]
461
494
 
462
- print('Stopping containers...')
495
+ print(f'Checking pip for Python: {sys.executable}', flush=True)
463
496
  try:
464
- subprocess.run([*base, 'down'], env=env, check=True)
497
+ update_command = _package_update_command()
465
498
  except subprocess.CalledProcessError as e:
499
+ print(f'Cannot use pip in {sys.executable}: {e.stderr or e}', file=sys.stderr)
466
500
  return e.returncode
467
- except FileNotFoundError:
468
- print('Docker not found.', file=sys.stderr)
501
+ except (OSError, RuntimeError, subprocess.TimeoutExpired) as e:
502
+ print(f'Cannot prepare package update: {e}', file=sys.stderr)
469
503
  return 1
470
504
 
471
- print(f'Updating {PYPI_PACKAGE} (pip install -U)...')
505
+ print(f'Updating {PYPI_PACKAGE} with {sys.executable} -m pip...', flush=True)
472
506
  try:
473
- subprocess.run([pip_exe, 'install', '-U', PYPI_PACKAGE], check=True, timeout=120)
507
+ subprocess.run(update_command, check=True, timeout=120)
474
508
  except subprocess.CalledProcessError as e:
475
509
  print(f'pip install -U {PYPI_PACKAGE} failed.', file=sys.stderr)
476
510
  return e.returncode
477
511
  except subprocess.TimeoutExpired:
478
512
  print('pip install timed out.', file=sys.stderr)
479
513
  return 1
514
+ except OSError as e:
515
+ print(f'Failed to start pip: {e}', file=sys.stderr)
516
+ return 1
480
517
 
481
- if not getattr(args, 'no_pull', False):
482
- print('Pulling latest images...')
483
- try:
484
- subprocess.run([*base, 'pull'], env=env, check=True)
485
- except subprocess.CalledProcessError as e:
486
- print(
487
- f'Warning: docker compose pull failed (exit {e.returncode}); '
488
- 'continuing with cached images.',
489
- file=sys.stderr,
490
- )
518
+ try:
519
+ package_dir = _updated_package_dir()
520
+ except subprocess.CalledProcessError as e:
521
+ print(f'Cannot locate updated package: {e.stderr or e}', file=sys.stderr)
522
+ return e.returncode
523
+ except (OSError, RuntimeError, subprocess.TimeoutExpired) as e:
524
+ print(f'Cannot locate updated package: {e}', file=sys.stderr)
525
+ return 1
526
+
527
+ compose_path = package_dir / 'docker/docker-compose.yml'
528
+ config_path = package_dir / 'config/config.yml'
529
+ for path in (compose_path, config_path):
530
+ if not path.is_file():
531
+ print(f'Updated package file not found: {path}', file=sys.stderr)
532
+ return 1
533
+ env = os.environ.copy()
534
+ env['CYCLO_MANAGER_CONFIG_FILE'] = str(config_path)
535
+ env.setdefault('HOSTNAME', socket.gethostname())
536
+ base = ['docker', 'compose', '-f', str(compose_path)]
491
537
 
492
- print('Starting containers...')
493
538
  try:
539
+ if not getattr(args, 'no_pull', False):
540
+ print('Pulling images before stopping containers...', flush=True)
541
+ subprocess.run([*base, 'pull'], env=env, check=True)
542
+
543
+ print('Stopping containers...', flush=True)
544
+ subprocess.run([*base, 'down'], env=env, check=True)
545
+ print('Starting containers...', flush=True)
494
546
  subprocess.run([*base, 'up', '-d', *COMPOSE_SERVICES_UP], env=env, check=True)
495
547
  subprocess.run(
496
548
  [*base, 'create', '--no-recreate', *COMPOSE_SERVICES_CREATE_ONLY],
@@ -498,7 +550,11 @@ def cmd_update(args: argparse.Namespace) -> int:
498
550
  check=True,
499
551
  )
500
552
  except subprocess.CalledProcessError as e:
553
+ print(f'Docker update command failed: {e}', file=sys.stderr)
501
554
  return e.returncode
555
+ except OSError as e:
556
+ print(f'Failed to run Docker: {e}', file=sys.stderr)
557
+ return 1
502
558
 
503
559
  print('Refreshing host agent (unit, socket, sudoers)...')
504
560
  if _refresh_host_agent_after_update() != 0:
@@ -533,7 +589,7 @@ def main() -> int:
533
589
 
534
590
  update_parser = sub.add_parser(
535
591
  'update',
536
- help='Down containers, pip install -U cyclo-manager, pull images, then up again',
592
+ help='Update the package and pull images before restarting containers and the host agent',
537
593
  )
538
594
  update_parser.add_argument(
539
595
  '--no-pull',
@@ -11,7 +11,7 @@ services:
11
11
 
12
12
  cyclo_manager:
13
13
  container_name: cyclo_manager
14
- image: robotis/cyclo-manager:1.2.1
14
+ image: robotis/cyclo-manager:1.2.2
15
15
  restart: always
16
16
  network_mode: host
17
17
  volumes:
@@ -29,7 +29,7 @@ services:
29
29
 
30
30
  ui:
31
31
  container_name: cyclo_manager_ui
32
- image: robotis/cyclo-manager-ui:1.2.1
32
+ image: robotis/cyclo-manager-ui:1.2.2
33
33
  restart: always
34
34
  network_mode: host
35
35
  environment:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "cyclo-manager"
7
- version = "1.2.1.dev"
7
+ version = "1.2.2.dev0"
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"