cyclo-manager 0.1.0__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.1.0/PKG-INFO +138 -0
- cyclo_manager-0.1.0/README.md +127 -0
- cyclo_manager-0.1.0/cyclo_manager.egg-info/PKG-INFO +138 -0
- cyclo_manager-0.1.0/cyclo_manager.egg-info/SOURCES.txt +13 -0
- cyclo_manager-0.1.0/cyclo_manager.egg-info/dependency_links.txt +1 -0
- cyclo_manager-0.1.0/cyclo_manager.egg-info/entry_points.txt +2 -0
- cyclo_manager-0.1.0/cyclo_manager.egg-info/requires.txt +4 -0
- cyclo_manager-0.1.0/cyclo_manager.egg-info/top_level.txt +1 -0
- cyclo_manager-0.1.0/cyclo_manager_cli/__init__.py +3 -0
- cyclo_manager-0.1.0/cyclo_manager_cli/cli.py +171 -0
- cyclo_manager-0.1.0/cyclo_manager_cli/config/config.yml +10 -0
- cyclo_manager-0.1.0/cyclo_manager_cli/docker/docker-compose.yml +54 -0
- cyclo_manager-0.1.0/pyproject.toml +28 -0
- cyclo_manager-0.1.0/setup.cfg +9 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cyclo-manager
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: cyclo_manager CLI: pip-installable launcher for cyclo_manager server and UI containers. Run 'cyclo_manager up' to start Docker stack.
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Provides-Extra: dev
|
|
9
|
+
Requires-Dist: pytest; extra == "dev"
|
|
10
|
+
Requires-Dist: ruff; extra == "dev"
|
|
11
|
+
|
|
12
|
+
# cyclo_manager CLI
|
|
13
|
+
|
|
14
|
+
**PyPI package:** `cyclo-manager`
|
|
15
|
+
**Console command:** `cyclo_manager` (underscore)
|
|
16
|
+
|
|
17
|
+
This package is a **thin launcher**: it runs **`docker compose`** against a **bundled** [`cyclo_manager_cli/docker/docker-compose.yml`](cyclo_manager_cli/docker/docker-compose.yml) so you can start the **cyclo_manager API** and **web UI** without cloning the monorepo. Optional services (**Zenoh**, **noVNC**) are **created** but **not started** by default. It can also **`pip install -U`** itself and bring the stack back up.
|
|
18
|
+
|
|
19
|
+
Implementation: [`cyclo_manager_cli/cli.py`](cyclo_manager_cli/cli.py).
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Table of contents
|
|
24
|
+
|
|
25
|
+
- [cyclo\_manager CLI](#cyclo_manager-cli)
|
|
26
|
+
- [Table of contents](#table-of-contents)
|
|
27
|
+
- [Prerequisites](#prerequisites)
|
|
28
|
+
- [Install](#install)
|
|
29
|
+
- [Commands](#commands)
|
|
30
|
+
- [Compose: services and behavior](#compose-services-and-behavior)
|
|
31
|
+
- [Config and environment](#config-and-environment)
|
|
32
|
+
- [Bundled `config.yml`](#bundled-configyml)
|
|
33
|
+
- [URLs (packaged stack)](#urls-packaged-stack)
|
|
34
|
+
- [Dependencies](#dependencies)
|
|
35
|
+
- [License](#license)
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Prerequisites
|
|
40
|
+
|
|
41
|
+
- **Docker** with **Compose v2** (`docker compose` — the legacy `docker-compose` binary alone is not enough)
|
|
42
|
+
- **Python 3.10+**
|
|
43
|
+
- For **`cyclo_manager update`:** **`pip`** or **`pip3`** on `PATH`
|
|
44
|
+
- On the **host:** agent sockets are expected under **`/var/run/robotis/agent_sockets`** and are mounted into the API container as **`/agents`** (see the bundled Compose file). Adjust only if you maintain a custom setup.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Install
|
|
49
|
+
|
|
50
|
+
Install from **PyPI**:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install cyclo-manager
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
If `cyclo_manager` is not on `PATH`, add the user script directory, e.g.:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
60
|
+
cyclo_manager up
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
If the entry point is still missing:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
python3 -m cyclo_manager_cli.cli --help
|
|
67
|
+
python3 -m cyclo_manager_cli.cli up
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Commands
|
|
73
|
+
|
|
74
|
+
| Command | Behavior |
|
|
75
|
+
|--------|----------|
|
|
76
|
+
| `cyclo_manager up` | `docker compose up -d` for **`cyclo_manager`** and **`ui`**, then `docker compose create --no-recreate` for **`rmw_zenoh`** and **`novnc-server`** so those containers **exist** but stay **stopped**. Sets **`CYCLO_MANAGER_CONFIG_FILE`** to the **bundled** [`cyclo_manager_cli/config/config.yml`](cyclo_manager_cli/config/config.yml) (no CLI flag to use another file). |
|
|
77
|
+
| `cyclo_manager up --pull` | Runs `docker compose pull` first, then the same as `up`. |
|
|
78
|
+
| `cyclo_manager down` | `docker compose down` using the **packaged** compose file. Stops and removes **all** services defined in that file for this Compose project (not only API + UI). |
|
|
79
|
+
| `cyclo_manager update` | Runs `cyclo_manager down`, `pip install -U cyclo-manager`, then `cyclo_manager up`. Optional `--pull` is passed through to the final `up`. Requires **`cyclo_manager`** and **`pip`** on `PATH`. |
|
|
80
|
+
| `cyclo_manager --help` | Subcommand overview |
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Compose: services and behavior
|
|
85
|
+
|
|
86
|
+
| Compose service | Container name (typical) | `cyclo_manager up` |
|
|
87
|
+
|-----------------|-------------------------|--------------------|
|
|
88
|
+
| `cyclo_manager` | `cyclo_manager` | **Started** |
|
|
89
|
+
| `ui` | `cyclo_manager_ui` | **Started** |
|
|
90
|
+
| `rmw_zenoh` | `zenoh_daemon` | **Created only** (start e.g. from the Control UI or `docker start zenoh_daemon`) |
|
|
91
|
+
| `novnc-server` | `novnc-server` | **Created only** (start when needed, e.g. `docker start novnc-server`) |
|
|
92
|
+
|
|
93
|
+
The bundled stack uses **`network_mode: host`** (see the Compose file). Image names and tags (e.g. `robotis/cyclo-manager`, `robotis/cyclo-manager-ui`) are defined in [`cyclo_manager_cli/docker/docker-compose.yml`](cyclo_manager_cli/docker/docker-compose.yml).
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Config and environment
|
|
98
|
+
|
|
99
|
+
- **`CYCLO_MANAGER_CONFIG_FILE`**: set automatically by the CLI to the absolute path of the **bundled** [`cyclo_manager_cli/config/config.yml`](cyclo_manager_cli/config/config.yml) on the host, and consumed by Compose as the mount for `/app/config.yml` in the API container. `up` and `down` both set this.
|
|
100
|
+
- **`ROS_DOMAIN_ID`**: **not** set by the CLI. Set DDS domain in each container’s environment (e.g. `~/.bashrc` inside the image) so it matches your robots, then restart as needed.
|
|
101
|
+
- For a **custom** config file, different mounts, or local source builds, use the repository’s **`docker-compose.dev.yml`** at the [project root](../README.md#how-to-run) instead of the pip-bundled workflow.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Bundled `config.yml`
|
|
106
|
+
|
|
107
|
+
Path: [`cyclo_manager_cli/config/config.yml`](cyclo_manager_cli/config/config.yml)
|
|
108
|
+
|
|
109
|
+
It only defines **which containers cyclo_manager knows about** and the **agent Unix socket path** (as seen from the API process, under `/agents` in the default Compose setup), for example:
|
|
110
|
+
|
|
111
|
+
- `ai_worker` → `/agents/ai_worker/s6_agent.sock`
|
|
112
|
+
- `physical_ai_server` → `/agents/physical_ai_server/s6_agent.sock`
|
|
113
|
+
|
|
114
|
+
**s6 service names** are **not** listed here; the agent in each container reports them at runtime.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## URLs (packaged stack)
|
|
119
|
+
|
|
120
|
+
With `network_mode: host` and the defaults in Compose:
|
|
121
|
+
|
|
122
|
+
| What | URL |
|
|
123
|
+
|------|-----|
|
|
124
|
+
| cyclo_manager API | http://127.0.0.1:8081 |
|
|
125
|
+
| OpenAPI (Swagger) | http://127.0.0.1:8081/docs |
|
|
126
|
+
| Web UI | http://127.0.0.1:3000 |
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Dependencies
|
|
131
|
+
|
|
132
|
+
The **`cyclo-manager`** package declares **no** Python runtime dependencies in [`pyproject.toml`](pyproject.toml). It invokes **`docker compose`** and, for **`update`**, **`pip`**.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
SPDX: **Apache-2.0** (see [pyproject.toml](pyproject.toml) and the repository [LICENSE](../LICENSE)).
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# cyclo_manager CLI
|
|
2
|
+
|
|
3
|
+
**PyPI package:** `cyclo-manager`
|
|
4
|
+
**Console command:** `cyclo_manager` (underscore)
|
|
5
|
+
|
|
6
|
+
This package is a **thin launcher**: it runs **`docker compose`** against a **bundled** [`cyclo_manager_cli/docker/docker-compose.yml`](cyclo_manager_cli/docker/docker-compose.yml) so you can start the **cyclo_manager API** and **web UI** without cloning the monorepo. Optional services (**Zenoh**, **noVNC**) are **created** but **not started** by default. It can also **`pip install -U`** itself and bring the stack back up.
|
|
7
|
+
|
|
8
|
+
Implementation: [`cyclo_manager_cli/cli.py`](cyclo_manager_cli/cli.py).
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Table of contents
|
|
13
|
+
|
|
14
|
+
- [cyclo\_manager CLI](#cyclo_manager-cli)
|
|
15
|
+
- [Table of contents](#table-of-contents)
|
|
16
|
+
- [Prerequisites](#prerequisites)
|
|
17
|
+
- [Install](#install)
|
|
18
|
+
- [Commands](#commands)
|
|
19
|
+
- [Compose: services and behavior](#compose-services-and-behavior)
|
|
20
|
+
- [Config and environment](#config-and-environment)
|
|
21
|
+
- [Bundled `config.yml`](#bundled-configyml)
|
|
22
|
+
- [URLs (packaged stack)](#urls-packaged-stack)
|
|
23
|
+
- [Dependencies](#dependencies)
|
|
24
|
+
- [License](#license)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Prerequisites
|
|
29
|
+
|
|
30
|
+
- **Docker** with **Compose v2** (`docker compose` — the legacy `docker-compose` binary alone is not enough)
|
|
31
|
+
- **Python 3.10+**
|
|
32
|
+
- For **`cyclo_manager update`:** **`pip`** or **`pip3`** on `PATH`
|
|
33
|
+
- On the **host:** agent sockets are expected under **`/var/run/robotis/agent_sockets`** and are mounted into the API container as **`/agents`** (see the bundled Compose file). Adjust only if you maintain a custom setup.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
Install from **PyPI**:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install cyclo-manager
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
If `cyclo_manager` is not on `PATH`, add the user script directory, e.g.:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
49
|
+
cyclo_manager up
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
If the entry point is still missing:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
python3 -m cyclo_manager_cli.cli --help
|
|
56
|
+
python3 -m cyclo_manager_cli.cli up
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Commands
|
|
62
|
+
|
|
63
|
+
| Command | Behavior |
|
|
64
|
+
|--------|----------|
|
|
65
|
+
| `cyclo_manager up` | `docker compose up -d` for **`cyclo_manager`** and **`ui`**, then `docker compose create --no-recreate` for **`rmw_zenoh`** and **`novnc-server`** so those containers **exist** but stay **stopped**. Sets **`CYCLO_MANAGER_CONFIG_FILE`** to the **bundled** [`cyclo_manager_cli/config/config.yml`](cyclo_manager_cli/config/config.yml) (no CLI flag to use another file). |
|
|
66
|
+
| `cyclo_manager up --pull` | Runs `docker compose pull` first, then the same as `up`. |
|
|
67
|
+
| `cyclo_manager down` | `docker compose down` using the **packaged** compose file. Stops and removes **all** services defined in that file for this Compose project (not only API + UI). |
|
|
68
|
+
| `cyclo_manager update` | Runs `cyclo_manager down`, `pip install -U cyclo-manager`, then `cyclo_manager up`. Optional `--pull` is passed through to the final `up`. Requires **`cyclo_manager`** and **`pip`** on `PATH`. |
|
|
69
|
+
| `cyclo_manager --help` | Subcommand overview |
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Compose: services and behavior
|
|
74
|
+
|
|
75
|
+
| Compose service | Container name (typical) | `cyclo_manager up` |
|
|
76
|
+
|-----------------|-------------------------|--------------------|
|
|
77
|
+
| `cyclo_manager` | `cyclo_manager` | **Started** |
|
|
78
|
+
| `ui` | `cyclo_manager_ui` | **Started** |
|
|
79
|
+
| `rmw_zenoh` | `zenoh_daemon` | **Created only** (start e.g. from the Control UI or `docker start zenoh_daemon`) |
|
|
80
|
+
| `novnc-server` | `novnc-server` | **Created only** (start when needed, e.g. `docker start novnc-server`) |
|
|
81
|
+
|
|
82
|
+
The bundled stack uses **`network_mode: host`** (see the Compose file). Image names and tags (e.g. `robotis/cyclo-manager`, `robotis/cyclo-manager-ui`) are defined in [`cyclo_manager_cli/docker/docker-compose.yml`](cyclo_manager_cli/docker/docker-compose.yml).
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Config and environment
|
|
87
|
+
|
|
88
|
+
- **`CYCLO_MANAGER_CONFIG_FILE`**: set automatically by the CLI to the absolute path of the **bundled** [`cyclo_manager_cli/config/config.yml`](cyclo_manager_cli/config/config.yml) on the host, and consumed by Compose as the mount for `/app/config.yml` in the API container. `up` and `down` both set this.
|
|
89
|
+
- **`ROS_DOMAIN_ID`**: **not** set by the CLI. Set DDS domain in each container’s environment (e.g. `~/.bashrc` inside the image) so it matches your robots, then restart as needed.
|
|
90
|
+
- For a **custom** config file, different mounts, or local source builds, use the repository’s **`docker-compose.dev.yml`** at the [project root](../README.md#how-to-run) instead of the pip-bundled workflow.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Bundled `config.yml`
|
|
95
|
+
|
|
96
|
+
Path: [`cyclo_manager_cli/config/config.yml`](cyclo_manager_cli/config/config.yml)
|
|
97
|
+
|
|
98
|
+
It only defines **which containers cyclo_manager knows about** and the **agent Unix socket path** (as seen from the API process, under `/agents` in the default Compose setup), for example:
|
|
99
|
+
|
|
100
|
+
- `ai_worker` → `/agents/ai_worker/s6_agent.sock`
|
|
101
|
+
- `physical_ai_server` → `/agents/physical_ai_server/s6_agent.sock`
|
|
102
|
+
|
|
103
|
+
**s6 service names** are **not** listed here; the agent in each container reports them at runtime.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## URLs (packaged stack)
|
|
108
|
+
|
|
109
|
+
With `network_mode: host` and the defaults in Compose:
|
|
110
|
+
|
|
111
|
+
| What | URL |
|
|
112
|
+
|------|-----|
|
|
113
|
+
| cyclo_manager API | http://127.0.0.1:8081 |
|
|
114
|
+
| OpenAPI (Swagger) | http://127.0.0.1:8081/docs |
|
|
115
|
+
| Web UI | http://127.0.0.1:3000 |
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Dependencies
|
|
120
|
+
|
|
121
|
+
The **`cyclo-manager`** package declares **no** Python runtime dependencies in [`pyproject.toml`](pyproject.toml). It invokes **`docker compose`** and, for **`update`**, **`pip`**.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
SPDX: **Apache-2.0** (see [pyproject.toml](pyproject.toml) and the repository [LICENSE](../LICENSE)).
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cyclo-manager
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: cyclo_manager CLI: pip-installable launcher for cyclo_manager server and UI containers. Run 'cyclo_manager up' to start Docker stack.
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Provides-Extra: dev
|
|
9
|
+
Requires-Dist: pytest; extra == "dev"
|
|
10
|
+
Requires-Dist: ruff; extra == "dev"
|
|
11
|
+
|
|
12
|
+
# cyclo_manager CLI
|
|
13
|
+
|
|
14
|
+
**PyPI package:** `cyclo-manager`
|
|
15
|
+
**Console command:** `cyclo_manager` (underscore)
|
|
16
|
+
|
|
17
|
+
This package is a **thin launcher**: it runs **`docker compose`** against a **bundled** [`cyclo_manager_cli/docker/docker-compose.yml`](cyclo_manager_cli/docker/docker-compose.yml) so you can start the **cyclo_manager API** and **web UI** without cloning the monorepo. Optional services (**Zenoh**, **noVNC**) are **created** but **not started** by default. It can also **`pip install -U`** itself and bring the stack back up.
|
|
18
|
+
|
|
19
|
+
Implementation: [`cyclo_manager_cli/cli.py`](cyclo_manager_cli/cli.py).
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Table of contents
|
|
24
|
+
|
|
25
|
+
- [cyclo\_manager CLI](#cyclo_manager-cli)
|
|
26
|
+
- [Table of contents](#table-of-contents)
|
|
27
|
+
- [Prerequisites](#prerequisites)
|
|
28
|
+
- [Install](#install)
|
|
29
|
+
- [Commands](#commands)
|
|
30
|
+
- [Compose: services and behavior](#compose-services-and-behavior)
|
|
31
|
+
- [Config and environment](#config-and-environment)
|
|
32
|
+
- [Bundled `config.yml`](#bundled-configyml)
|
|
33
|
+
- [URLs (packaged stack)](#urls-packaged-stack)
|
|
34
|
+
- [Dependencies](#dependencies)
|
|
35
|
+
- [License](#license)
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Prerequisites
|
|
40
|
+
|
|
41
|
+
- **Docker** with **Compose v2** (`docker compose` — the legacy `docker-compose` binary alone is not enough)
|
|
42
|
+
- **Python 3.10+**
|
|
43
|
+
- For **`cyclo_manager update`:** **`pip`** or **`pip3`** on `PATH`
|
|
44
|
+
- On the **host:** agent sockets are expected under **`/var/run/robotis/agent_sockets`** and are mounted into the API container as **`/agents`** (see the bundled Compose file). Adjust only if you maintain a custom setup.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Install
|
|
49
|
+
|
|
50
|
+
Install from **PyPI**:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install cyclo-manager
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
If `cyclo_manager` is not on `PATH`, add the user script directory, e.g.:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
60
|
+
cyclo_manager up
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
If the entry point is still missing:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
python3 -m cyclo_manager_cli.cli --help
|
|
67
|
+
python3 -m cyclo_manager_cli.cli up
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Commands
|
|
73
|
+
|
|
74
|
+
| Command | Behavior |
|
|
75
|
+
|--------|----------|
|
|
76
|
+
| `cyclo_manager up` | `docker compose up -d` for **`cyclo_manager`** and **`ui`**, then `docker compose create --no-recreate` for **`rmw_zenoh`** and **`novnc-server`** so those containers **exist** but stay **stopped**. Sets **`CYCLO_MANAGER_CONFIG_FILE`** to the **bundled** [`cyclo_manager_cli/config/config.yml`](cyclo_manager_cli/config/config.yml) (no CLI flag to use another file). |
|
|
77
|
+
| `cyclo_manager up --pull` | Runs `docker compose pull` first, then the same as `up`. |
|
|
78
|
+
| `cyclo_manager down` | `docker compose down` using the **packaged** compose file. Stops and removes **all** services defined in that file for this Compose project (not only API + UI). |
|
|
79
|
+
| `cyclo_manager update` | Runs `cyclo_manager down`, `pip install -U cyclo-manager`, then `cyclo_manager up`. Optional `--pull` is passed through to the final `up`. Requires **`cyclo_manager`** and **`pip`** on `PATH`. |
|
|
80
|
+
| `cyclo_manager --help` | Subcommand overview |
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Compose: services and behavior
|
|
85
|
+
|
|
86
|
+
| Compose service | Container name (typical) | `cyclo_manager up` |
|
|
87
|
+
|-----------------|-------------------------|--------------------|
|
|
88
|
+
| `cyclo_manager` | `cyclo_manager` | **Started** |
|
|
89
|
+
| `ui` | `cyclo_manager_ui` | **Started** |
|
|
90
|
+
| `rmw_zenoh` | `zenoh_daemon` | **Created only** (start e.g. from the Control UI or `docker start zenoh_daemon`) |
|
|
91
|
+
| `novnc-server` | `novnc-server` | **Created only** (start when needed, e.g. `docker start novnc-server`) |
|
|
92
|
+
|
|
93
|
+
The bundled stack uses **`network_mode: host`** (see the Compose file). Image names and tags (e.g. `robotis/cyclo-manager`, `robotis/cyclo-manager-ui`) are defined in [`cyclo_manager_cli/docker/docker-compose.yml`](cyclo_manager_cli/docker/docker-compose.yml).
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Config and environment
|
|
98
|
+
|
|
99
|
+
- **`CYCLO_MANAGER_CONFIG_FILE`**: set automatically by the CLI to the absolute path of the **bundled** [`cyclo_manager_cli/config/config.yml`](cyclo_manager_cli/config/config.yml) on the host, and consumed by Compose as the mount for `/app/config.yml` in the API container. `up` and `down` both set this.
|
|
100
|
+
- **`ROS_DOMAIN_ID`**: **not** set by the CLI. Set DDS domain in each container’s environment (e.g. `~/.bashrc` inside the image) so it matches your robots, then restart as needed.
|
|
101
|
+
- For a **custom** config file, different mounts, or local source builds, use the repository’s **`docker-compose.dev.yml`** at the [project root](../README.md#how-to-run) instead of the pip-bundled workflow.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Bundled `config.yml`
|
|
106
|
+
|
|
107
|
+
Path: [`cyclo_manager_cli/config/config.yml`](cyclo_manager_cli/config/config.yml)
|
|
108
|
+
|
|
109
|
+
It only defines **which containers cyclo_manager knows about** and the **agent Unix socket path** (as seen from the API process, under `/agents` in the default Compose setup), for example:
|
|
110
|
+
|
|
111
|
+
- `ai_worker` → `/agents/ai_worker/s6_agent.sock`
|
|
112
|
+
- `physical_ai_server` → `/agents/physical_ai_server/s6_agent.sock`
|
|
113
|
+
|
|
114
|
+
**s6 service names** are **not** listed here; the agent in each container reports them at runtime.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## URLs (packaged stack)
|
|
119
|
+
|
|
120
|
+
With `network_mode: host` and the defaults in Compose:
|
|
121
|
+
|
|
122
|
+
| What | URL |
|
|
123
|
+
|------|-----|
|
|
124
|
+
| cyclo_manager API | http://127.0.0.1:8081 |
|
|
125
|
+
| OpenAPI (Swagger) | http://127.0.0.1:8081/docs |
|
|
126
|
+
| Web UI | http://127.0.0.1:3000 |
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Dependencies
|
|
131
|
+
|
|
132
|
+
The **`cyclo-manager`** package declares **no** Python runtime dependencies in [`pyproject.toml`](pyproject.toml). It invokes **`docker compose`** and, for **`update`**, **`pip`**.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
SPDX: **Apache-2.0** (see [pyproject.toml](pyproject.toml) and the repository [LICENSE](../LICENSE)).
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
setup.cfg
|
|
4
|
+
cyclo_manager.egg-info/PKG-INFO
|
|
5
|
+
cyclo_manager.egg-info/SOURCES.txt
|
|
6
|
+
cyclo_manager.egg-info/dependency_links.txt
|
|
7
|
+
cyclo_manager.egg-info/entry_points.txt
|
|
8
|
+
cyclo_manager.egg-info/requires.txt
|
|
9
|
+
cyclo_manager.egg-info/top_level.txt
|
|
10
|
+
cyclo_manager_cli/__init__.py
|
|
11
|
+
cyclo_manager_cli/cli.py
|
|
12
|
+
cyclo_manager_cli/config/config.yml
|
|
13
|
+
cyclo_manager_cli/docker/docker-compose.yml
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cyclo_manager_cli
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""CLI for pip-installed cyclo_manager_cli: cyclo_manager up, cyclo_manager down, cyclo_manager update. Launches cyclo_manager server and UI via Docker."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import os
|
|
5
|
+
import shutil
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
PYPI_PACKAGE = "cyclo-manager"
|
|
11
|
+
|
|
12
|
+
# `cyclo_manager up` starts these immediately.
|
|
13
|
+
COMPOSE_SERVICES_UP = ("cyclo_manager", "ui")
|
|
14
|
+
# These get `docker compose create` only (stopped); start from UI or `docker start` when needed.
|
|
15
|
+
COMPOSE_SERVICES_CREATE_ONLY = ("rmw_zenoh", "novnc-server")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _docker_dir() -> Path:
|
|
19
|
+
return Path(__file__).resolve().parent / "docker"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _config_dir() -> Path:
|
|
23
|
+
return Path(__file__).resolve().parent / "config"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _packaged_config_path() -> Path:
|
|
27
|
+
"""Path to the bundled config (config/config.yml). Used for cyclo_manager up/down."""
|
|
28
|
+
return _config_dir() / "config.yml"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def cmd_up(args: argparse.Namespace) -> int:
|
|
32
|
+
"""Run docker compose: start API + UI; create zenoh + noVNC containers without starting them."""
|
|
33
|
+
config_path = _packaged_config_path()
|
|
34
|
+
if not config_path.is_file():
|
|
35
|
+
print(f"Bundled config not found: {config_path}", file=sys.stderr)
|
|
36
|
+
return 1
|
|
37
|
+
compose_path = _docker_dir() / "docker-compose.yml"
|
|
38
|
+
if not compose_path.is_file():
|
|
39
|
+
print(f"Compose file not found: {compose_path}", file=sys.stderr)
|
|
40
|
+
return 1
|
|
41
|
+
env = os.environ.copy()
|
|
42
|
+
env["CYCLO_MANAGER_CONFIG_FILE"] = str(config_path)
|
|
43
|
+
base = ["docker", "compose", "-f", str(compose_path)]
|
|
44
|
+
try:
|
|
45
|
+
if args.pull:
|
|
46
|
+
subprocess.run([*base, "pull"], env=env, check=True)
|
|
47
|
+
subprocess.run([*base, "up", "-d", *COMPOSE_SERVICES_UP], env=env, check=True)
|
|
48
|
+
subprocess.run(
|
|
49
|
+
[*base, "create", "--no-recreate", *COMPOSE_SERVICES_CREATE_ONLY],
|
|
50
|
+
env=env,
|
|
51
|
+
check=True,
|
|
52
|
+
)
|
|
53
|
+
except subprocess.CalledProcessError as e:
|
|
54
|
+
return e.returncode
|
|
55
|
+
except FileNotFoundError:
|
|
56
|
+
print(
|
|
57
|
+
"Docker not found. Install Docker and ensure 'docker compose' is available.",
|
|
58
|
+
file=sys.stderr,
|
|
59
|
+
)
|
|
60
|
+
return 1
|
|
61
|
+
print("cyclo_manager stack is up (API + UI running; zenoh_daemon + novnc-server created, not started).")
|
|
62
|
+
return 0
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def cmd_down(args: argparse.Namespace) -> int:
|
|
66
|
+
"""Stop cyclo_manager server, cyclo_manager_ui, and zenoh daemon (docker compose down)."""
|
|
67
|
+
compose_path = _docker_dir() / "docker-compose.yml"
|
|
68
|
+
if not compose_path.is_file():
|
|
69
|
+
print(f"Compose file not found: {compose_path}", file=sys.stderr)
|
|
70
|
+
return 1
|
|
71
|
+
env = os.environ.copy()
|
|
72
|
+
env["CYCLO_MANAGER_CONFIG_FILE"] = str(_packaged_config_path())
|
|
73
|
+
cmd = [
|
|
74
|
+
"docker",
|
|
75
|
+
"compose",
|
|
76
|
+
"-f",
|
|
77
|
+
str(compose_path),
|
|
78
|
+
"down",
|
|
79
|
+
]
|
|
80
|
+
try:
|
|
81
|
+
subprocess.run(cmd, env=env, check=True)
|
|
82
|
+
except subprocess.CalledProcessError as e:
|
|
83
|
+
return e.returncode
|
|
84
|
+
except FileNotFoundError:
|
|
85
|
+
print(
|
|
86
|
+
"Docker not found. Install Docker and ensure 'docker compose' is available.",
|
|
87
|
+
file=sys.stderr,
|
|
88
|
+
)
|
|
89
|
+
return 1
|
|
90
|
+
print("cyclo_manager server, cyclo_manager_ui, and zenoh daemon are down.")
|
|
91
|
+
return 0
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def cmd_update(args: argparse.Namespace) -> int:
|
|
95
|
+
"""Down containers, pip install -U cyclo-manager, then up again."""
|
|
96
|
+
cyclo_manager_exe = shutil.which("cyclo_manager")
|
|
97
|
+
if not cyclo_manager_exe:
|
|
98
|
+
print("cyclo_manager command not found in PATH.", file=sys.stderr)
|
|
99
|
+
return 1
|
|
100
|
+
pip_exe = shutil.which("pip3") or shutil.which("pip")
|
|
101
|
+
if not pip_exe:
|
|
102
|
+
print("pip not found; cannot update package.", file=sys.stderr)
|
|
103
|
+
return 1
|
|
104
|
+
|
|
105
|
+
print("Stopping containers (cyclo_manager down)...")
|
|
106
|
+
try:
|
|
107
|
+
subprocess.run([cyclo_manager_exe, "down"], check=True)
|
|
108
|
+
except subprocess.CalledProcessError as e:
|
|
109
|
+
return e.returncode
|
|
110
|
+
|
|
111
|
+
print(f"Updating {PYPI_PACKAGE} (pip install -U)...")
|
|
112
|
+
try:
|
|
113
|
+
subprocess.run(
|
|
114
|
+
[pip_exe, "install", "-U", PYPI_PACKAGE],
|
|
115
|
+
check=True,
|
|
116
|
+
timeout=120,
|
|
117
|
+
)
|
|
118
|
+
except subprocess.CalledProcessError as e:
|
|
119
|
+
print(f"pip install -U {PYPI_PACKAGE} failed.", file=sys.stderr)
|
|
120
|
+
return e.returncode
|
|
121
|
+
except subprocess.TimeoutExpired:
|
|
122
|
+
print("pip install timed out.", file=sys.stderr)
|
|
123
|
+
return 1
|
|
124
|
+
|
|
125
|
+
print("Starting containers (cyclo_manager up)...")
|
|
126
|
+
up_args = [cyclo_manager_exe, "up"]
|
|
127
|
+
if getattr(args, "pull", False):
|
|
128
|
+
up_args.append("--pull")
|
|
129
|
+
try:
|
|
130
|
+
subprocess.run(up_args, check=True)
|
|
131
|
+
except subprocess.CalledProcessError as e:
|
|
132
|
+
return e.returncode
|
|
133
|
+
|
|
134
|
+
print("cyclo_manager update completed.")
|
|
135
|
+
return 0
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def main() -> int:
|
|
139
|
+
parser = argparse.ArgumentParser(
|
|
140
|
+
prog="cyclo_manager",
|
|
141
|
+
description="cyclo_manager CLI: launch cyclo_manager server and UI containers. Services run via Docker images.",
|
|
142
|
+
)
|
|
143
|
+
sub = parser.add_subparsers(dest="command", help="Commands")
|
|
144
|
+
|
|
145
|
+
up_parser = sub.add_parser("up", help="Start cyclo_manager stack (docker compose)")
|
|
146
|
+
up_parser.add_argument(
|
|
147
|
+
"--pull",
|
|
148
|
+
action="store_true",
|
|
149
|
+
help="Pull all service images before create/up",
|
|
150
|
+
)
|
|
151
|
+
up_parser.set_defaults(func=cmd_up)
|
|
152
|
+
|
|
153
|
+
down_parser = sub.add_parser("down", help="Stop all stack containers (docker compose down)")
|
|
154
|
+
down_parser.set_defaults(func=cmd_down)
|
|
155
|
+
|
|
156
|
+
update_parser = sub.add_parser(
|
|
157
|
+
"update",
|
|
158
|
+
help="Down containers, pip install -U cyclo-manager, then up again",
|
|
159
|
+
)
|
|
160
|
+
update_parser.add_argument(
|
|
161
|
+
"--pull",
|
|
162
|
+
action="store_true",
|
|
163
|
+
help="Always pull images when running cyclo_manager up",
|
|
164
|
+
)
|
|
165
|
+
update_parser.set_defaults(func=cmd_update)
|
|
166
|
+
|
|
167
|
+
args = parser.parse_args()
|
|
168
|
+
if not args.command:
|
|
169
|
+
parser.print_help()
|
|
170
|
+
return 0
|
|
171
|
+
return args.func(args)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# cyclo_manager Configuration
|
|
2
|
+
# This file defines the containers that cyclo_manager can control.
|
|
3
|
+
#
|
|
4
|
+
# Services are discovered dynamically from each agent.
|
|
5
|
+
|
|
6
|
+
containers:
|
|
7
|
+
ai_worker:
|
|
8
|
+
socket_path: "/agents/ai_worker/s6_agent.sock"
|
|
9
|
+
physical_ai_server:
|
|
10
|
+
socket_path: "/agents/physical_ai_server/s6_agent.sock"
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Packaged compose for pip-installed cyclo_manager_cli.
|
|
2
|
+
# Uses pre-built images; config path is set via CYCLO_MANAGER_CONFIG_FILE by the CLI.
|
|
3
|
+
# `cyclo_manager up` starts cyclo_manager + ui only; rmw_zenoh + novnc-server are created but left stopped.
|
|
4
|
+
services:
|
|
5
|
+
rmw_zenoh:
|
|
6
|
+
container_name: zenoh_daemon
|
|
7
|
+
image: robotis/zenoh-daemon:latest
|
|
8
|
+
restart: always
|
|
9
|
+
network_mode: host
|
|
10
|
+
init: true
|
|
11
|
+
|
|
12
|
+
cyclo_manager:
|
|
13
|
+
container_name: cyclo_manager
|
|
14
|
+
image: robotis/cyclo-manager:0.1.0
|
|
15
|
+
restart: always
|
|
16
|
+
network_mode: host
|
|
17
|
+
volumes:
|
|
18
|
+
- /dev:/dev
|
|
19
|
+
- /dev/shm:/dev/shm
|
|
20
|
+
- /var/run/robotis/agent_sockets:/agents # For agent socket access
|
|
21
|
+
- ${CYCLO_MANAGER_CONFIG_FILE}:/app/config.yml # For hot-reload on config changes
|
|
22
|
+
- /var/run/docker.sock:/var/run/docker.sock # For Docker API access
|
|
23
|
+
environment:
|
|
24
|
+
- CONFIG_FILE=/app/config.yml
|
|
25
|
+
|
|
26
|
+
ui:
|
|
27
|
+
container_name: cyclo_manager_ui
|
|
28
|
+
image: robotis/cyclo-manager-ui:0.1.0
|
|
29
|
+
restart: always
|
|
30
|
+
network_mode: host
|
|
31
|
+
environment:
|
|
32
|
+
- NEXT_PUBLIC_API_URL=http://127.0.0.1:8081
|
|
33
|
+
- NODE_ENV=production
|
|
34
|
+
|
|
35
|
+
novnc-server:
|
|
36
|
+
container_name: novnc-server
|
|
37
|
+
image: robotis/novnc-server:latest
|
|
38
|
+
restart: always
|
|
39
|
+
cap_add:
|
|
40
|
+
- SYS_NICE
|
|
41
|
+
ulimits:
|
|
42
|
+
rtprio: 99
|
|
43
|
+
rttime: -1
|
|
44
|
+
memlock: 8428281856
|
|
45
|
+
network_mode: host
|
|
46
|
+
environment:
|
|
47
|
+
- DISPLAY=:99
|
|
48
|
+
- DISPLAY_WIDTH=1920
|
|
49
|
+
- DISPLAY_HEIGHT=1080
|
|
50
|
+
- WEBSOCKIFY_PORT=8090
|
|
51
|
+
volumes:
|
|
52
|
+
- /dev:/dev
|
|
53
|
+
- /dev/shm:/dev/shm
|
|
54
|
+
privileged: true
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "cyclo-manager"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "cyclo_manager CLI: pip-installable launcher for cyclo_manager server and UI containers. Run 'cyclo_manager up' to start Docker stack."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "Apache-2.0"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
dependencies = []
|
|
13
|
+
|
|
14
|
+
[project.optional-dependencies]
|
|
15
|
+
dev = [
|
|
16
|
+
"pytest",
|
|
17
|
+
"ruff",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.scripts]
|
|
21
|
+
cyclo_manager = "cyclo_manager_cli.cli:main"
|
|
22
|
+
|
|
23
|
+
[tool.setuptools.packages.find]
|
|
24
|
+
where = ["."]
|
|
25
|
+
include = ["cyclo_manager_cli*"]
|
|
26
|
+
|
|
27
|
+
[tool.setuptools.package-data]
|
|
28
|
+
cyclo_manager_cli = ["docker/*.yml", "docker/*.yaml", "config/*.yml", "config/*.yaml"]
|