vmware-storage 2.3.1__tar.gz → 2.4.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.
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/.claude-plugin/plugin.json +1 -1
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/.mcp.json +1 -1
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/PKG-INFO +2 -1
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/README-CN.md +1 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/README.md +1 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/RELEASE_NOTES.md +9 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/openclaw.plugin.json +1 -1
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/package.json +1 -1
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/pyproject.toml +1 -1
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/server.json +2 -2
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/skills/vmware-storage/SKILL.md +2 -2
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/skills/vmware-storage/references/setup-guide.md +4 -3
- vmware_storage-2.4.0/tests/test_policy_roles.py +55 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/uv.lock +4 -4
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/__init__.py +1 -1
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/policy_environment.py +4 -0
- vmware_storage-2.4.0/vmware_storage/policy_roles.py +52 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/.clawhubignore +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/.env.example +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/.gitignore +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/Dockerfile +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/LICENSE +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/SECURITY.md +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/config.example.yaml +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/docker-compose.yml +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/examples/mcp-configs/README.md +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/examples/mcp-configs/claude-code.json +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/examples/mcp-configs/continue.yaml +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/examples/mcp-configs/cursor.json +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/examples/mcp-configs/goose.json +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/examples/mcp-configs/localcowork.json +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/examples/mcp-configs/mcp-agent.yaml +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/examples/mcp-configs/vscode-copilot.json +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/patterns/README.md +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/patterns/iscsi-target-stale-rescan.yaml +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/skills/vmware-storage/evals/evals.json +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/skills/vmware-storage/references/agent-guardrails.md +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/skills/vmware-storage/references/capabilities.md +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/skills/vmware-storage/references/cli-reference.md +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/smithery.yaml +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/__init__.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/conftest.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/__init__.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/capability/__init__.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/capability/_family.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/capability/_scores.json +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/capability/_scoring.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/capability/_skill.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/capability/conftest.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/capability/test_entity_reachability.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/capability/test_error_actionability.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/capability/test_tool_description_quality.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/capability/test_tool_manifest_budget.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/__init__.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_atexit_handlers_do_not_accumulate.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_audit_isolation.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_cached_loader_agrees_with_the_resolver.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_capability_grader.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_cli_writes_guarded.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_credential_env_override.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_datastore_list_renders.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_doctor_authenticates_every_target.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_doctor_uses_the_config_the_tools_use.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_env_secret_obfuscation.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_fc_multipath.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_instructions_name_targets.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_inventory_scale_n1.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_iscsi_unreachable_host.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_login_without_a_role.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_release_blockers.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_remedy_survives_a_long_home.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_result_envelope.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_returned_failure_is_audited.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_session_probe_eviction.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_storage_hardening_fixes.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_storage_ops_behavior.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_tool_names_2_0.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_vim_attribute_conformance.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_vsan_efficiency.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_vsan_health_is_actually_queried.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_vsan_reports_what_it_could_not_read.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/spec/__init__.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/spec/vsan_efficiency_endpoints.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/spec/vsan_health_endpoints.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/test_access_info.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/test_init_and_onboarding.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/test_iscsi_gate.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/test_no_destructive_ops.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/test_no_destructive_vm_code.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/test_safe_error_passthrough.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/test_session_pool.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/test_stop_signal_runs_atexit.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/access_requirements.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/cli.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/config.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/connection.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/doctor.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/init_wizard.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/mcp_server/__init__.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/mcp_server/__main__.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/mcp_server/server.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/notify/__init__.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/notify/audit.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/ops/__init__.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/ops/datastore_browser.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/ops/inventory.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/ops/iscsi_config.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/ops/iscsi_gate.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/ops/multipath.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/ops/storage_paths.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/ops/vsan.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/ops/vsan_efficiency.py +0 -0
- {vmware_storage-2.3.1 → vmware_storage-2.4.0}/vmware_storage/ops/vsan_sdk.py +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://anthropic.com/claude-code/plugin.schema.json",
|
|
3
3
|
"name": "vmware-storage",
|
|
4
4
|
"displayName": "VMware Storage",
|
|
5
|
-
"version": "2.
|
|
5
|
+
"version": "2.4.0",
|
|
6
6
|
"description": "VMware vSphere storage with 15 MCP tools: datastores, iSCSI, vSAN, FC multipath.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Wei Zhou",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: vmware-storage
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: VMware vSphere storage management: datastores, iSCSI, vSAN. Domain-focused MCP skill.
|
|
5
5
|
Project-URL: Homepage, https://github.com/vmware-skills/VMware-Storage
|
|
6
6
|
Project-URL: Repository, https://github.com/vmware-skills/VMware-Storage
|
|
@@ -329,6 +329,7 @@ claude mcp add --transport http vmware-storage https://mcp.example.com:8443/mcp
|
|
|
329
329
|
- The audit log records each caller as `token:<name>`. Calls run side by side, also on the same target: the server keeps up to `VMWARE_MCP_POOL_SIZE` (default 2) sessions per target, each one a login on that target, and a call waits at most 300 s for a free session (vmware-policy ≥ 1.22.0).
|
|
330
330
|
- **Everyone who can reach the endpoint acts with this server's account.** Tokens identify callers; they grant
|
|
331
331
|
nothing on the platform. Run one endpoint per privilege level. `vmware-storage access-info` shows which account that is and what it may do.
|
|
332
|
+
- **Several people or roles on one endpoint:** run `vmware-audit roles enable` once, then give each token a role (`vmware-audit token create NAME --role reader`, or a role in `roles.yaml` naming tools and targets; vmware-policy ≥ 1.24.0). A role limits what the token may call on this endpoint; it cannot grant more than the account has. See vmware-policy's README, "Roles for network callers".
|
|
332
333
|
|
|
333
334
|
**Offer only read tools, plus the writes you choose:**
|
|
334
335
|
|
|
@@ -341,6 +341,7 @@ claude mcp add --transport http vmware-storage https://mcp.example.com:8443/mcp
|
|
|
341
341
|
- 审计日志把每个调用者记为 `token:<名字>`。调用并行执行,同一 target 上也一样:server 为每个 target 最多保持 `VMWARE_MCP_POOL_SIZE`(默认 2)个会话,每个会话都是在该 target 上的一次登录;一个调用最多等 300 秒拿到空闲会话(vmware-policy ≥ 1.22.0)。
|
|
342
342
|
- **能连到这个端点的人,都以该 server 配置的账号操作。** token 只用来识别调用者,不在平台上授予任何权限。
|
|
343
343
|
每个权限级别单独起一个端点。`vmware-storage access-info` 可查看是哪个账号、它能做什么。
|
|
344
|
+
- **一个端点给多人或多种角色用:** 先运行一次 `vmware-audit roles enable`,再给每个 token 指定角色(`vmware-audit token create 名字 --role reader`,或在 `roles.yaml` 里定义可用的工具和 target;需 vmware-policy ≥ 1.24.0)。角色只能限定这个 token 在本端点上能调用什么,不能超出账号本身的权限。详见 vmware-policy README 的「网络调用者的角色」一节。
|
|
344
345
|
|
|
345
346
|
**只提供读工具,加上你选定的写工具:**
|
|
346
347
|
|
|
@@ -308,6 +308,7 @@ claude mcp add --transport http vmware-storage https://mcp.example.com:8443/mcp
|
|
|
308
308
|
- The audit log records each caller as `token:<name>`. Calls run side by side, also on the same target: the server keeps up to `VMWARE_MCP_POOL_SIZE` (default 2) sessions per target, each one a login on that target, and a call waits at most 300 s for a free session (vmware-policy ≥ 1.22.0).
|
|
309
309
|
- **Everyone who can reach the endpoint acts with this server's account.** Tokens identify callers; they grant
|
|
310
310
|
nothing on the platform. Run one endpoint per privilege level. `vmware-storage access-info` shows which account that is and what it may do.
|
|
311
|
+
- **Several people or roles on one endpoint:** run `vmware-audit roles enable` once, then give each token a role (`vmware-audit token create NAME --role reader`, or a role in `roles.yaml` naming tools and targets; vmware-policy ≥ 1.24.0). A role limits what the token may call on this endpoint; it cannot grant more than the account has. See vmware-policy's README, "Roles for network callers".
|
|
311
312
|
|
|
312
313
|
**Offer only read tools, plus the writes you choose:**
|
|
313
314
|
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## v2.4.0 — roles for network callers (HLD §18)
|
|
2
|
+
|
|
3
|
+
* Declares the role metadata vmware-policy ≥ 1.24.0 needs to apply **roles** to this server over HTTPS
|
|
4
|
+
(HLD §18): how a missing target resolves. With an older vmware-policy nothing changes. Once an operator runs
|
|
5
|
+
`vmware-audit roles enable`, a token's role decides which tools and targets it may use here; a refused call is
|
|
6
|
+
audited as `denied`. See vmware-policy's README, "Roles for network callers".
|
|
7
|
+
* A target-limited role is checked against the same config the connection uses: the copy the server's connection manager loaded on its first connection. Edit `config.yaml` and restart for both to see the change.
|
|
8
|
+
* README and setup guide: one endpoint for several people or roles.
|
|
9
|
+
|
|
1
10
|
## v2.3.1 — a login with no vSphere role is named as such (AIops#47)
|
|
2
11
|
|
|
3
12
|
* An account that logs in but has no vSphere role (vCenter shows no session for it) is now refused at connect time
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"url": "https://github.com/vmware-skills/VMware-Storage",
|
|
8
8
|
"source": "github"
|
|
9
9
|
},
|
|
10
|
-
"version": "2.
|
|
10
|
+
"version": "2.4.0",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "pypi",
|
|
14
14
|
"identifier": "vmware-storage",
|
|
15
|
-
"version": "2.
|
|
15
|
+
"version": "2.4.0",
|
|
16
16
|
"runtimeHint": "uvx",
|
|
17
17
|
"packageArguments": [
|
|
18
18
|
{
|
|
@@ -40,7 +40,7 @@ VMware vSphere storage management — 15 MCP tools for datastores, iSCSI, vSAN,
|
|
|
40
40
|
## Quick Install
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
uv tool install vmware-storage==2.
|
|
43
|
+
uv tool install vmware-storage==2.4.0
|
|
44
44
|
vmware-storage init # guided setup: writes config + .env (chmod 600, password grep-safe), then verifies
|
|
45
45
|
vmware-storage doctor
|
|
46
46
|
```
|
|
@@ -271,7 +271,7 @@ Corporate TLS proxies inject certificates that uv's bundled CA store doesn't tru
|
|
|
271
271
|
## Setup
|
|
272
272
|
|
|
273
273
|
```bash
|
|
274
|
-
uv tool install vmware-storage==2.
|
|
274
|
+
uv tool install vmware-storage==2.4.0
|
|
275
275
|
mkdir -p ~/.vmware-storage
|
|
276
276
|
cp config.example.yaml ~/.vmware-storage/config.yaml
|
|
277
277
|
# Edit config.yaml with your vCenter/ESXi targets
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/skills/vmware-storage/references/setup-guide.md
RENAMED
|
@@ -13,19 +13,19 @@ Complete setup and security guide for `vmware-storage`.
|
|
|
13
13
|
### Via uv (recommended)
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
uv tool install vmware-storage==2.
|
|
16
|
+
uv tool install vmware-storage==2.4.0
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
### Via pip
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
pip install vmware-storage==2.
|
|
22
|
+
pip install vmware-storage==2.4.0
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
### From source
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
git clone --branch v2.
|
|
28
|
+
git clone --branch v2.4.0 https://github.com/vmware-skills/VMware-Storage.git
|
|
29
29
|
cd VMware-Storage
|
|
30
30
|
pip install -e .
|
|
31
31
|
```
|
|
@@ -250,6 +250,7 @@ vmware-storage mcp --transport https --host 0.0.0.0 --port 8443 \
|
|
|
250
250
|
- **Everyone who can reach the endpoint acts with this server's account.** Tokens identify callers; they grant
|
|
251
251
|
nothing on the platform. Run one endpoint per privilege level (for example a read-only account behind
|
|
252
252
|
`--expose read`, and a separate endpoint for operators).
|
|
253
|
+
- **Several people or roles on one endpoint:** run `vmware-audit roles enable` once, then give each token a role (`vmware-audit token create NAME --role reader`, or a role in `roles.yaml` naming tools and targets; vmware-policy ≥ 1.24.0). A role limits what the token may call on this endpoint; it cannot grant more than the account has. See vmware-policy's README, "Roles for network callers".
|
|
253
254
|
|
|
254
255
|
## Security Details
|
|
255
256
|
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""HLD §18: the role metadata this skill declares matches its real tools."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from vmware_storage import policy_roles
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _registry() -> set[str]:
|
|
13
|
+
from vmware_storage.mcp_server.server import mcp
|
|
14
|
+
|
|
15
|
+
return {t.name for t in asyncio.run(mcp.list_tools())}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.mark.unit
|
|
19
|
+
def test_every_declared_name_is_a_real_tool():
|
|
20
|
+
named = set(policy_roles.ESCAPES) | set(getattr(policy_roles, "AKO_TOOLS", ()))
|
|
21
|
+
assert named - _registry() == set(), sorted(named - _registry())
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@pytest.mark.unit
|
|
25
|
+
def test_metadata_is_declared_when_policy_has_roles():
|
|
26
|
+
roles = pytest.importorskip("vmware_policy.roles")
|
|
27
|
+
import vmware_storage.mcp_server.server # noqa: F401 (registers the metadata on import)
|
|
28
|
+
|
|
29
|
+
meta = roles.metadata("storage")
|
|
30
|
+
assert meta is not None and meta.version == 1
|
|
31
|
+
assert meta.escapes == policy_roles.ESCAPES
|
|
32
|
+
assert (meta.resolver is not None) is True
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@pytest.mark.unit
|
|
36
|
+
def test_the_resolver_uses_the_config_the_connection_manager_holds(monkeypatch):
|
|
37
|
+
"""Review H1/H-1: once the server's connection manager exists, a config edit must
|
|
38
|
+
not move the role check off the config it connects with; before, read the file."""
|
|
39
|
+
import importlib
|
|
40
|
+
import types
|
|
41
|
+
|
|
42
|
+
from vmware_storage import policy_roles as pr
|
|
43
|
+
|
|
44
|
+
server = importlib.import_module("vmware_storage.mcp_server.server")
|
|
45
|
+
assert hasattr(server, "_conn_mgr"), "policy_roles looks up a global the server does not have"
|
|
46
|
+
edited, loads = object(), []
|
|
47
|
+
monkeypatch.setattr(pr, "load_config", lambda: loads.append(1) or edited)
|
|
48
|
+
|
|
49
|
+
monkeypatch.setattr(server, "_conn_mgr", None)
|
|
50
|
+
assert pr._connection_config() is edited and pr._connection_config() is edited
|
|
51
|
+
assert len(loads) == 2 # no manager yet: the file as it is now, every time
|
|
52
|
+
|
|
53
|
+
held = object()
|
|
54
|
+
monkeypatch.setattr(server, "_conn_mgr", types.SimpleNamespace(_config=held))
|
|
55
|
+
assert pr._connection_config() is held # the manager's copy, not the edited file
|
|
@@ -1162,21 +1162,21 @@ wheels = [
|
|
|
1162
1162
|
|
|
1163
1163
|
[[package]]
|
|
1164
1164
|
name = "vmware-policy"
|
|
1165
|
-
version = "1.
|
|
1165
|
+
version = "1.24.0"
|
|
1166
1166
|
source = { registry = "https://pypi.org/simple" }
|
|
1167
1167
|
dependencies = [
|
|
1168
1168
|
{ name = "pyyaml" },
|
|
1169
1169
|
{ name = "rich" },
|
|
1170
1170
|
{ name = "typer" },
|
|
1171
1171
|
]
|
|
1172
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1172
|
+
sdist = { url = "https://files.pythonhosted.org/packages/4a/62/3a3cb83af77e3dd3c8fc92cb3b7968bfda04a2f71bf0d6f9b72ee3198441/vmware_policy-1.24.0.tar.gz", hash = "sha256:fba12732ccbd4371232c15d9fd014f9f5d697497210aedff2515d1d205ed3577", size = 361302, upload-time = "2026-10-16T07:18:28.317Z" }
|
|
1173
1173
|
wheels = [
|
|
1174
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1174
|
+
{ url = "https://files.pythonhosted.org/packages/3d/f2/fe3d9d384712023916e2cacddc385f14b095509c5e00aea417d1a9550e98/vmware_policy-1.24.0-py3-none-any.whl", hash = "sha256:cf615d0256134f01fb84c39b083649281a66d2c064c2eaa28786a0fa95ec6e58", size = 131460, upload-time = "2026-10-16T07:18:26.907Z" },
|
|
1175
1175
|
]
|
|
1176
1176
|
|
|
1177
1177
|
[[package]]
|
|
1178
1178
|
name = "vmware-storage"
|
|
1179
|
-
version = "2.
|
|
1179
|
+
version = "2.4.0"
|
|
1180
1180
|
source = { editable = "." }
|
|
1181
1181
|
dependencies = [
|
|
1182
1182
|
{ name = "mcp", extra = ["cli"] },
|
|
@@ -38,3 +38,7 @@ def _environment_for(target: str | None) -> str:
|
|
|
38
38
|
# to ALLOW. Keyed, a resolver only ever answers for its own skill, so
|
|
39
39
|
# registering at import time is safe again.
|
|
40
40
|
set_environment_resolver(_environment_for, skill=skill_name(__name__))
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# Role metadata (HLD §18) is declared beside the environment resolver, on every surface.
|
|
44
|
+
import vmware_storage.policy_roles # noqa: E402,F401
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""What vmware-policy needs to apply roles to this skill (HLD §18 D-21/D-22).
|
|
2
|
+
|
|
3
|
+
Policy cannot see which tools escape a role or how a missing target resolves; this
|
|
4
|
+
module declares them. Imported by ``policy_environment``, so the MCP server and
|
|
5
|
+
the CLI both register it. With a vmware-policy that has no roles module (< 1.24)
|
|
6
|
+
nothing is declared.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import sys
|
|
12
|
+
|
|
13
|
+
from vmware_policy import skill_name
|
|
14
|
+
|
|
15
|
+
from vmware_storage.config import load_config
|
|
16
|
+
|
|
17
|
+
#: Tools that give their holder more than a role. Host-path tools are added by
|
|
18
|
+
#: policy while a file root is set.
|
|
19
|
+
ESCAPES = frozenset()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _connection_config():
|
|
23
|
+
"""The config the connection layer uses for this call (review H1, then H-1).
|
|
24
|
+
|
|
25
|
+
The server's connection manager loads the config once, on its first connection,
|
|
26
|
+
and keeps it. Once it exists, the role is checked against that same object, so
|
|
27
|
+
an edit to config.yaml cannot move the check off the target the call connects
|
|
28
|
+
to. Before it exists, the file as it is now is what the manager is about to load.
|
|
29
|
+
Looked up in ``sys.modules`` so the CLI never imports the MCP server.
|
|
30
|
+
"""
|
|
31
|
+
server = sys.modules.get("vmware_storage.mcp_server.server")
|
|
32
|
+
manager = getattr(server, "_conn_mgr", None) if server is not None else None
|
|
33
|
+
return manager._config if manager is not None else load_config()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _target_name(target: str | None) -> str:
|
|
37
|
+
"""The target the connection layer would use for ``target`` (or the default)."""
|
|
38
|
+
config = _connection_config()
|
|
39
|
+
return (config.get_target(target) if target else config.default_target).name
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
from vmware_policy.roles import declare_role_metadata
|
|
44
|
+
except ImportError: # vmware-policy without roles: nothing to declare
|
|
45
|
+
declare_role_metadata = None
|
|
46
|
+
|
|
47
|
+
if declare_role_metadata is not None:
|
|
48
|
+
declare_role_metadata(
|
|
49
|
+
skill_name(__name__),
|
|
50
|
+
escapes=ESCAPES,
|
|
51
|
+
resolver=_target_name,
|
|
52
|
+
)
|
|
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
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/skills/vmware-storage/references/agent-guardrails.md
RENAMED
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/skills/vmware-storage/references/capabilities.md
RENAMED
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/skills/vmware-storage/references/cli-reference.md
RENAMED
|
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
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/capability/test_entity_reachability.py
RENAMED
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/capability/test_error_actionability.py
RENAMED
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/capability/test_tool_description_quality.py
RENAMED
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/capability/test_tool_manifest_budget.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_capability_grader.py
RENAMED
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_cli_writes_guarded.py
RENAMED
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_credential_env_override.py
RENAMED
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_datastore_list_renders.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_env_secret_obfuscation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_inventory_scale_n1.py
RENAMED
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_iscsi_unreachable_host.py
RENAMED
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_login_without_a_role.py
RENAMED
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_release_blockers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_session_probe_eviction.py
RENAMED
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_storage_hardening_fixes.py
RENAMED
|
File without changes
|
{vmware_storage-2.3.1 → vmware_storage-2.4.0}/tests/eval/regression/test_storage_ops_behavior.py
RENAMED
|
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
|
|
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
|