flowmesh-cli-stack 0.1.1__tar.gz → 0.1.3rc1__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.
- {flowmesh_cli_stack-0.1.1/src/flowmesh_cli_stack.egg-info → flowmesh_cli_stack-0.1.3rc1}/PKG-INFO +3 -3
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/pyproject.toml +3 -3
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack/assets/.env.example +16 -4
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack/assets/compose.yml +4 -0
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack/env_schema.py +38 -4
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack/stack.py +2 -0
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack/utils.py +24 -0
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack/worker.py +23 -1
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1/src/flowmesh_cli_stack.egg-info}/PKG-INFO +3 -3
- flowmesh_cli_stack-0.1.3rc1/src/flowmesh_cli_stack.egg-info/requires.txt +5 -0
- flowmesh_cli_stack-0.1.1/src/flowmesh_cli_stack.egg-info/requires.txt +0 -5
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/LICENSE +0 -0
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/README.md +0 -0
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/setup.cfg +0 -0
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack/__init__.py +0 -0
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack/assets/docker-bake.hcl +0 -0
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack/bundle.py +0 -0
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack.egg-info/SOURCES.txt +0 -0
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack.egg-info/dependency_links.txt +0 -0
- {flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack.egg-info/top_level.txt +0 -0
{flowmesh_cli_stack-0.1.1/src/flowmesh_cli_stack.egg-info → flowmesh_cli_stack-0.1.3rc1}/PKG-INFO
RENAMED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flowmesh-cli-stack
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3rc1
|
|
4
4
|
Summary: FlowMesh CLI stack commands
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.12
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
License-File: LICENSE
|
|
9
|
-
Requires-Dist: flowmesh-cli==0.1.
|
|
10
|
-
Requires-Dist: flowmesh-sdk-stack==0.1.
|
|
9
|
+
Requires-Dist: flowmesh-cli==0.1.3rc1
|
|
10
|
+
Requires-Dist: flowmesh-sdk-stack==0.1.3rc1
|
|
11
11
|
Requires-Dist: docker>=7.1.0
|
|
12
12
|
Requires-Dist: packaging>=24
|
|
13
13
|
Requires-Dist: pyyaml>=6.0.2
|
|
@@ -4,15 +4,15 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "flowmesh-cli-stack"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.3rc1"
|
|
8
8
|
description = "FlowMesh CLI stack commands"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
11
11
|
license = "Apache-2.0"
|
|
12
12
|
license-files = ["LICENSE"]
|
|
13
13
|
dependencies = [
|
|
14
|
-
"flowmesh-cli==0.1.
|
|
15
|
-
"flowmesh-sdk-stack==0.1.
|
|
14
|
+
"flowmesh-cli==0.1.3rc1",
|
|
15
|
+
"flowmesh-sdk-stack==0.1.3rc1",
|
|
16
16
|
"docker>=7.1.0",
|
|
17
17
|
"packaging>=24",
|
|
18
18
|
"pyyaml>=6.0.2",
|
{flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack/assets/.env.example
RENAMED
|
@@ -93,6 +93,13 @@ SSH_DEFAULT_IDLE_SEC=
|
|
|
93
93
|
SSH_MAX_TTL_SEC=
|
|
94
94
|
SSH_POLL_INTERVAL_SEC=
|
|
95
95
|
SSH_STOP_TIMEOUT_SEC=
|
|
96
|
+
SSH_MAX_CPU=
|
|
97
|
+
SSH_MAX_MEMORY=
|
|
98
|
+
SSH_MAX_PIDS=
|
|
99
|
+
# Whether to apply requested GPU limits to SSH tasks.
|
|
100
|
+
# If false, SSH tasks are allocated all available GPUs
|
|
101
|
+
# regardless of their resource requests.
|
|
102
|
+
ENABLE_SSH_GPU_LIMIT=false
|
|
96
103
|
|
|
97
104
|
# ==== General Settings ====
|
|
98
105
|
TZ=Asia/Singapore
|
|
@@ -110,6 +117,7 @@ TASK_MERGE_MAX_BATCH_SIZE=4
|
|
|
110
117
|
ENABLE_CONTEXT_REUSE=true
|
|
111
118
|
WORKER_CACHE_TTL_SEC=3600
|
|
112
119
|
ENABLE_STAGE_WEIGHT_STICKINESS=false
|
|
120
|
+
TASK_NO_WORKER_GRACE_SEC=60
|
|
113
121
|
ENABLE_WORKER_WATCHDOG=true
|
|
114
122
|
WORKER_DEATH_CHECK_INTERVAL=30
|
|
115
123
|
WORKER_DEATH_GRACE_SEC=60
|
|
@@ -166,11 +174,15 @@ NEBULA_API_TOKEN=
|
|
|
166
174
|
|
|
167
175
|
# ==== External Plugins ====
|
|
168
176
|
# Plugins are Python packages dropped under FLOWMESH_PLUGIN_DIR
|
|
169
|
-
# (
|
|
170
|
-
#
|
|
171
|
-
#
|
|
172
|
-
#
|
|
177
|
+
# (read-only at /app/plugins) and selected by FLOWMESH_PLUGINS as
|
|
178
|
+
# a comma-separated list of top-level module names. Each must
|
|
179
|
+
# expose `install()` returning a `HookBindings`.
|
|
180
|
+
# FLOWMESH_PLUGIN_DATA_DIR is writable at /app/plugin-data for
|
|
181
|
+
# plugin state. Leave all empty unless you ship a plugin.
|
|
173
182
|
FLOWMESH_PLUGIN_DIR=./plugins
|
|
183
|
+
# A path (`./x`, `/abs/x`) -> host bind-mount (auto-created).
|
|
184
|
+
# A bare name -> external Docker volume of that name.
|
|
185
|
+
FLOWMESH_PLUGIN_DATA_DIR=./plugin-data
|
|
174
186
|
FLOWMESH_PLUGINS=
|
|
175
187
|
|
|
176
188
|
# ==== Agent Executor (youtu-agent / utu) ====
|
{flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack/assets/compose.yml
RENAMED
|
@@ -166,6 +166,7 @@ services:
|
|
|
166
166
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
167
167
|
- ${SERVER_WORKER_CONFIG:-./configs/worker_config.yaml}:/etc/flowmesh/worker_config.yaml:ro
|
|
168
168
|
- ${FLOWMESH_PLUGIN_DIR:-./plugins}:/app/plugins:ro
|
|
169
|
+
- ${FLOWMESH_PLUGIN_DATA_DIR:-./plugin-data}:/app/plugin-data
|
|
169
170
|
- ${REDIS_TLS_DIR:-./secrets/tls/redis}:/etc/ssl/redis:ro
|
|
170
171
|
- ${SERVER_TLS_DIR:-./secrets/tls/server}:/etc/ssl/server:ro
|
|
171
172
|
restart: unless-stopped
|
|
@@ -199,3 +200,6 @@ volumes:
|
|
|
199
200
|
name: ${FLOWMESH_STACK_SLUG:-flowmesh_node}_metrics
|
|
200
201
|
flowmesh_server_logs:
|
|
201
202
|
name: ${FLOWMESH_STACK_SLUG:-flowmesh_node}_server_logs
|
|
203
|
+
flowmesh_plugin_data:
|
|
204
|
+
external: true
|
|
205
|
+
name: ${FLOWMESH_PLUGIN_DATA_VOLUME:-${FLOWMESH_STACK_SLUG:-flowmesh_node}_plugin_data}
|
{flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack/env_schema.py
RENAMED
|
@@ -301,6 +301,24 @@ STACK_ENV_SCHEMA = EnvSchema(
|
|
|
301
301
|
EnvVar("SSH_MAX_TTL_SEC", var_type=EnvVarType.FLOAT, min_value=0),
|
|
302
302
|
EnvVar("SSH_POLL_INTERVAL_SEC", var_type=EnvVarType.FLOAT, min_value=0),
|
|
303
303
|
EnvVar("SSH_STOP_TIMEOUT_SEC", var_type=EnvVarType.FLOAT, min_value=0),
|
|
304
|
+
EnvVar(
|
|
305
|
+
"SSH_MAX_CPU",
|
|
306
|
+
var_type=EnvVarType.FLOAT,
|
|
307
|
+
min_value=0,
|
|
308
|
+
min_inclusive=False,
|
|
309
|
+
),
|
|
310
|
+
EnvVar("SSH_MAX_MEMORY"),
|
|
311
|
+
EnvVar("SSH_MAX_PIDS", var_type=EnvVarType.INT, min_value=1),
|
|
312
|
+
EnvVar(
|
|
313
|
+
"ENABLE_SSH_GPU_LIMIT",
|
|
314
|
+
"false",
|
|
315
|
+
var_type=EnvVarType.BOOL,
|
|
316
|
+
description=[
|
|
317
|
+
"Whether to apply requested GPU limits to SSH tasks.",
|
|
318
|
+
"If false, SSH tasks are allocated all available GPUs",
|
|
319
|
+
"regardless of their resource requests.",
|
|
320
|
+
],
|
|
321
|
+
),
|
|
304
322
|
],
|
|
305
323
|
),
|
|
306
324
|
EnvSection(
|
|
@@ -370,6 +388,12 @@ STACK_ENV_SCHEMA = EnvSchema(
|
|
|
370
388
|
"false",
|
|
371
389
|
var_type=EnvVarType.BOOL,
|
|
372
390
|
),
|
|
391
|
+
EnvVar(
|
|
392
|
+
"TASK_NO_WORKER_GRACE_SEC",
|
|
393
|
+
"60",
|
|
394
|
+
var_type=EnvVarType.INT,
|
|
395
|
+
min_value=0,
|
|
396
|
+
),
|
|
373
397
|
EnvVar("ENABLE_WORKER_WATCHDOG", "true", var_type=EnvVarType.BOOL),
|
|
374
398
|
EnvVar(
|
|
375
399
|
"WORKER_DEATH_CHECK_INTERVAL",
|
|
@@ -512,10 +536,11 @@ STACK_ENV_SCHEMA = EnvSchema(
|
|
|
512
536
|
title="External Plugins",
|
|
513
537
|
description=[
|
|
514
538
|
"Plugins are Python packages dropped under FLOWMESH_PLUGIN_DIR ",
|
|
515
|
-
"(
|
|
516
|
-
"
|
|
517
|
-
"
|
|
518
|
-
"
|
|
539
|
+
"(read-only at /app/plugins) and selected by FLOWMESH_PLUGINS as ",
|
|
540
|
+
"a comma-separated list of top-level module names. Each must ",
|
|
541
|
+
"expose `install()` returning a `HookBindings`. ",
|
|
542
|
+
"FLOWMESH_PLUGIN_DATA_DIR is writable at /app/plugin-data for ",
|
|
543
|
+
"plugin state. Leave all empty unless you ship a plugin.",
|
|
519
544
|
],
|
|
520
545
|
vars=[
|
|
521
546
|
EnvVar(
|
|
@@ -525,6 +550,15 @@ STACK_ENV_SCHEMA = EnvSchema(
|
|
|
525
550
|
use_default=True,
|
|
526
551
|
ensure_path="create",
|
|
527
552
|
),
|
|
553
|
+
EnvVar(
|
|
554
|
+
"FLOWMESH_PLUGIN_DATA_DIR",
|
|
555
|
+
"./plugin-data",
|
|
556
|
+
use_default=True,
|
|
557
|
+
description=[
|
|
558
|
+
"A path (`./x`, `/abs/x`) -> host bind-mount (auto-created).",
|
|
559
|
+
"A bare name -> external Docker volume of that name.",
|
|
560
|
+
],
|
|
561
|
+
),
|
|
528
562
|
EnvVar("FLOWMESH_PLUGINS", ""),
|
|
529
563
|
],
|
|
530
564
|
),
|
|
@@ -35,6 +35,7 @@ from .env_schema import STACK_ENV_SCHEMA, deploy_overrides, role_overrides
|
|
|
35
35
|
from .utils import (
|
|
36
36
|
DEFAULT_ENV_FILE,
|
|
37
37
|
STACK_PATH_KEYS,
|
|
38
|
+
apply_plugin_data_env,
|
|
38
39
|
apply_stack_resource_env,
|
|
39
40
|
ensure_deploy_paths,
|
|
40
41
|
parse_node_role,
|
|
@@ -58,6 +59,7 @@ def _stack() -> DockerComposeStack:
|
|
|
58
59
|
except ValueError as exc:
|
|
59
60
|
logging.error(str(exc))
|
|
60
61
|
raise typer.Exit(code=1)
|
|
62
|
+
apply_plugin_data_env(Path.cwd())
|
|
61
63
|
|
|
62
64
|
return DockerComposeStack(
|
|
63
65
|
compose_file=stack_compose_file(),
|
|
@@ -57,6 +57,22 @@ def apply_stack_resource_env() -> None:
|
|
|
57
57
|
os.environ[WORKER_RESULTS_DIR_ENV] = results_volume
|
|
58
58
|
|
|
59
59
|
|
|
60
|
+
_PLUGIN_DATA_PATH_PREFIXES = ("/", "./", "../", "~")
|
|
61
|
+
_PLUGIN_DATA_ALIAS = "flowmesh_plugin_data"
|
|
62
|
+
_PLUGIN_DATA_DEFAULT = "./plugin-data"
|
|
63
|
+
_PLUGIN_DATA_VOLUME_ENV = "FLOWMESH_PLUGIN_DATA_VOLUME"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def apply_plugin_data_env(base_dir: Path) -> None:
|
|
67
|
+
raw = os.environ.get("FLOWMESH_PLUGIN_DATA_DIR", "").strip()
|
|
68
|
+
if not raw or raw.startswith(_PLUGIN_DATA_PATH_PREFIXES):
|
|
69
|
+
resolved = resolve_path(raw, default=_PLUGIN_DATA_DEFAULT, base_dir=base_dir)
|
|
70
|
+
os.environ["FLOWMESH_PLUGIN_DATA_DIR"] = resolved.as_posix()
|
|
71
|
+
else:
|
|
72
|
+
os.environ[_PLUGIN_DATA_VOLUME_ENV] = raw
|
|
73
|
+
os.environ["FLOWMESH_PLUGIN_DATA_DIR"] = _PLUGIN_DATA_ALIAS
|
|
74
|
+
|
|
75
|
+
|
|
60
76
|
def stack_compose_file() -> Path:
|
|
61
77
|
return asset_path("flowmesh_cli_stack.assets", "compose.yml")
|
|
62
78
|
|
|
@@ -118,6 +134,14 @@ def ensure_deploy_paths(base_dir: Path) -> None:
|
|
|
118
134
|
base_dir=base_dir,
|
|
119
135
|
)
|
|
120
136
|
)
|
|
137
|
+
if not os.environ.get(_PLUGIN_DATA_VOLUME_ENV):
|
|
138
|
+
ensure_dir(
|
|
139
|
+
resolve_path(
|
|
140
|
+
os.getenv("FLOWMESH_PLUGIN_DATA_DIR", ""),
|
|
141
|
+
default=_PLUGIN_DATA_DEFAULT,
|
|
142
|
+
base_dir=base_dir,
|
|
143
|
+
)
|
|
144
|
+
)
|
|
121
145
|
|
|
122
146
|
|
|
123
147
|
def parse_node_role(raw: str) -> NodeRole:
|
|
@@ -18,7 +18,13 @@ from flowmesh_stack.workers import (
|
|
|
18
18
|
select_worker_images,
|
|
19
19
|
)
|
|
20
20
|
|
|
21
|
-
from .utils import
|
|
21
|
+
from .utils import (
|
|
22
|
+
DEFAULT_ENV_FILE,
|
|
23
|
+
STACK_PATH_KEYS,
|
|
24
|
+
STACK_SLUG_ENV,
|
|
25
|
+
stack_node_client,
|
|
26
|
+
stack_resource_env_overrides,
|
|
27
|
+
)
|
|
22
28
|
|
|
23
29
|
app = get_typer(help="Create and manage workers on the local node.")
|
|
24
30
|
|
|
@@ -74,6 +80,15 @@ def worker_up(
|
|
|
74
80
|
"Repeat --config-raw to provide multiple configs."
|
|
75
81
|
),
|
|
76
82
|
),
|
|
83
|
+
name_template: str | None = typer.Option(
|
|
84
|
+
None,
|
|
85
|
+
"--name-template",
|
|
86
|
+
help=(
|
|
87
|
+
"Worker name template for cpu/gpu presets. Placeholders: "
|
|
88
|
+
"{slug}, {kind}, {idx}, {gpu}. "
|
|
89
|
+
"Default: '{slug}_worker_{kind}_{idx|gpu}'."
|
|
90
|
+
),
|
|
91
|
+
),
|
|
77
92
|
env_file: Path = typer.Option(
|
|
78
93
|
DEFAULT_ENV_FILE, "--env-file", help="Env file to load defaults"
|
|
79
94
|
),
|
|
@@ -84,6 +99,11 @@ def worker_up(
|
|
|
84
99
|
) -> None:
|
|
85
100
|
"""Create and start one or more workers from presets or a custom config file."""
|
|
86
101
|
client = stack_node_client(env_file, base_url, token or None)
|
|
102
|
+
try:
|
|
103
|
+
slug = stack_resource_env_overrides(os.environ)[STACK_SLUG_ENV]
|
|
104
|
+
except ValueError as exc:
|
|
105
|
+
logging.error(str(exc))
|
|
106
|
+
raise typer.Exit(code=1)
|
|
87
107
|
logging.info("Creating workers...")
|
|
88
108
|
try:
|
|
89
109
|
created = create_workers(
|
|
@@ -93,6 +113,8 @@ def worker_up(
|
|
|
93
113
|
targets=targets,
|
|
94
114
|
config_paths=config,
|
|
95
115
|
config_raw=config_raw,
|
|
116
|
+
name_template=name_template,
|
|
117
|
+
slug=slug,
|
|
96
118
|
)
|
|
97
119
|
except FlowMeshError as exc:
|
|
98
120
|
logging.error(str(exc))
|
{flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1/src/flowmesh_cli_stack.egg-info}/PKG-INFO
RENAMED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flowmesh-cli-stack
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3rc1
|
|
4
4
|
Summary: FlowMesh CLI stack commands
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.12
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
License-File: LICENSE
|
|
9
|
-
Requires-Dist: flowmesh-cli==0.1.
|
|
10
|
-
Requires-Dist: flowmesh-sdk-stack==0.1.
|
|
9
|
+
Requires-Dist: flowmesh-cli==0.1.3rc1
|
|
10
|
+
Requires-Dist: flowmesh-sdk-stack==0.1.3rc1
|
|
11
11
|
Requires-Dist: docker>=7.1.0
|
|
12
12
|
Requires-Dist: packaging>=24
|
|
13
13
|
Requires-Dist: pyyaml>=6.0.2
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flowmesh_cli_stack-0.1.1 → flowmesh_cli_stack-0.1.3rc1}/src/flowmesh_cli_stack.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|