zen-cli 0.1.1__tar.gz → 0.1.4__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.
- {zen_cli-0.1.1 → zen_cli-0.1.4}/.gitignore +3 -0
- zen_cli-0.1.4/PKG-INFO +98 -0
- zen_cli-0.1.4/README.md +66 -0
- zen_cli-0.1.4/pyproject.toml +75 -0
- zen_cli-0.1.4/src/zen_cli/__init__.py +5 -0
- zen_cli-0.1.4/src/zen_cli/__main__.py +4 -0
- zen_cli-0.1.4/src/zen_cli/cli.py +176 -0
- zen_cli-0.1.4/src/zen_cli/cmds/activity/__init__.py +1 -0
- zen_cli-0.1.4/src/zen_cli/cmds/activity/get.py +20 -0
- zen_cli-0.1.4/src/zen_cli/cmds/activity/list.py +157 -0
- zen_cli-0.1.4/src/zen_cli/cmds/api.py +145 -0
- zen_cli-0.1.4/src/zen_cli/cmds/auth/__init__.py +1 -0
- zen_cli-0.1.4/src/zen_cli/cmds/auth/details.py +19 -0
- zen_cli-0.1.4/src/zen_cli/cmds/auth/refresh.py +11 -0
- zen_cli-0.1.4/src/zen_cli/cmds/auth/status.py +17 -0
- zen_cli-0.1.4/src/zen_cli/cmds/auth/token.py +17 -0
- zen_cli-0.1.4/src/zen_cli/cmds/completion.py +29 -0
- zen_cli-0.1.4/src/zen_cli/cmds/credential/__init__.py +1 -0
- zen_cli-0.1.4/src/zen_cli/cmds/credential/create.py +13 -0
- zen_cli-0.1.4/src/zen_cli/cmds/credential/delete.py +27 -0
- zen_cli-0.1.4/src/zen_cli/cmds/credential/get.py +19 -0
- zen_cli-0.1.4/src/zen_cli/cmds/credential/list.py +18 -0
- zen_cli-0.1.4/src/zen_cli/cmds/deployment/__init__.py +1 -0
- zen_cli-0.1.4/src/zen_cli/cmds/deployment/create.py +15 -0
- zen_cli-0.1.4/src/zen_cli/cmds/deployment/delete.py +28 -0
- zen_cli-0.1.4/src/zen_cli/cmds/deployment/get.py +19 -0
- zen_cli-0.1.4/src/zen_cli/cmds/deployment/list.py +27 -0
- zen_cli-0.1.4/src/zen_cli/cmds/entitlement/__init__.py +1 -0
- zen_cli-0.1.4/src/zen_cli/cmds/entitlement/create.py +13 -0
- zen_cli-0.1.4/src/zen_cli/cmds/entitlement/delete.py +27 -0
- zen_cli-0.1.4/src/zen_cli/cmds/entitlement/get.py +19 -0
- zen_cli-0.1.4/src/zen_cli/cmds/entitlement/list.py +19 -0
- zen_cli-0.1.4/src/zen_cli/cmds/group/__init__.py +1 -0
- zen_cli-0.1.4/src/zen_cli/cmds/group/create.py +13 -0
- zen_cli-0.1.4/src/zen_cli/cmds/group/delete.py +33 -0
- zen_cli-0.1.4/src/zen_cli/cmds/group/get.py +19 -0
- zen_cli-0.1.4/src/zen_cli/cmds/group/list.py +26 -0
- zen_cli-0.1.4/src/zen_cli/cmds/login.py +375 -0
- zen_cli-0.1.4/src/zen_cli/cmds/logout.py +9 -0
- zen_cli-0.1.4/src/zen_cli/cmds/mcp.py +13 -0
- zen_cli-0.1.4/src/zen_cli/cmds/network/__init__.py +1 -0
- zen_cli-0.1.4/src/zen_cli/cmds/network/create.py +13 -0
- zen_cli-0.1.4/src/zen_cli/cmds/network/delete.py +34 -0
- zen_cli-0.1.4/src/zen_cli/cmds/network/get.py +19 -0
- zen_cli-0.1.4/src/zen_cli/cmds/network/list.py +27 -0
- zen_cli-0.1.4/src/zen_cli/cmds/notification/__init__.py +1 -0
- zen_cli-0.1.4/src/zen_cli/cmds/notification/get.py +19 -0
- zen_cli-0.1.4/src/zen_cli/cmds/notification/list.py +66 -0
- zen_cli-0.1.4/src/zen_cli/cmds/org/__init__.py +1 -0
- zen_cli-0.1.4/src/zen_cli/cmds/org/create.py +13 -0
- zen_cli-0.1.4/src/zen_cli/cmds/org/get.py +51 -0
- zen_cli-0.1.4/src/zen_cli/cmds/org/list.py +33 -0
- zen_cli-0.1.4/src/zen_cli/cmds/org/use.py +46 -0
- zen_cli-0.1.4/src/zen_cli/cmds/pool/__init__.py +1 -0
- zen_cli-0.1.4/src/zen_cli/cmds/pool/create.py +13 -0
- zen_cli-0.1.4/src/zen_cli/cmds/pool/delete.py +34 -0
- zen_cli-0.1.4/src/zen_cli/cmds/pool/get.py +19 -0
- zen_cli-0.1.4/src/zen_cli/cmds/pool/list.py +93 -0
- zen_cli-0.1.4/src/zen_cli/cmds/pool/use.py +35 -0
- zen_cli-0.1.4/src/zen_cli/cmds/profile/__init__.py +1 -0
- zen_cli-0.1.4/src/zen_cli/cmds/profile/init.py +10 -0
- zen_cli-0.1.4/src/zen_cli/cmds/provider/__init__.py +1 -0
- zen_cli-0.1.4/src/zen_cli/cmds/provider/create.py +13 -0
- zen_cli-0.1.4/src/zen_cli/cmds/provider/delete.py +27 -0
- zen_cli-0.1.4/src/zen_cli/cmds/provider/get.py +27 -0
- zen_cli-0.1.4/src/zen_cli/cmds/provider/list.py +43 -0
- zen_cli-0.1.4/src/zen_cli/cmds/sag/__init__.py +1 -0
- zen_cli-0.1.4/src/zen_cli/cmds/sag/create.py +13 -0
- zen_cli-0.1.4/src/zen_cli/cmds/sag/delete.py +34 -0
- zen_cli-0.1.4/src/zen_cli/cmds/sag/get.py +19 -0
- zen_cli-0.1.4/src/zen_cli/cmds/sag/list.py +20 -0
- zen_cli-0.1.4/src/zen_cli/cmds/task/__init__.py +1 -0
- zen_cli-0.1.4/src/zen_cli/cmds/task/cancel.py +27 -0
- zen_cli-0.1.4/src/zen_cli/cmds/task/delete.py +42 -0
- zen_cli-0.1.4/src/zen_cli/cmds/task/duplicate.py +75 -0
- zen_cli-0.1.4/src/zen_cli/cmds/task/get.py +20 -0
- zen_cli-0.1.4/src/zen_cli/cmds/task/list.py +132 -0
- zen_cli-0.1.4/src/zen_cli/cmds/task/log.py +60 -0
- zen_cli-0.1.4/src/zen_cli/cmds/task/namespaces.py +11 -0
- zen_cli-0.1.4/src/zen_cli/cmds/task/use.py +37 -0
- zen_cli-0.1.4/src/zen_cli/cmds/task/wait.py +28 -0
- zen_cli-0.1.4/src/zen_cli/cmds/upgrade.py +13 -0
- zen_cli-0.1.4/src/zen_cli/cmds/vm/__init__.py +1 -0
- zen_cli-0.1.4/src/zen_cli/cmds/vm/delete.py +39 -0
- zen_cli-0.1.4/src/zen_cli/cmds/vm/get.py +17 -0
- zen_cli-0.1.4/src/zen_cli/cmds/vm/list.py +184 -0
- zen_cli-0.1.4/src/zen_cli/cmds/vm/poweroff.py +29 -0
- zen_cli-0.1.4/src/zen_cli/cmds/vm/poweron.py +29 -0
- zen_cli-0.1.4/src/zen_cli/cmds/vm/restart.py +19 -0
- zen_cli-0.1.4/src/zen_cli/cmds/vm/shutdown.py +19 -0
- zen_cli-0.1.4/src/zen_cli/cmds/vm/use.py +48 -0
- zen_cli-0.1.4/src/zen_cli/cmds/vm/wait.py +48 -0
- zen_cli-0.1.4/src/zen_cli/config/default.yaml +31 -0
- zen_cli-0.1.4/src/zen_cli/config/int.yaml +21 -0
- zen_cli-0.1.4/src/zen_cli/config/prod.yaml +31 -0
- zen_cli-0.1.4/src/zen_cli/config/stg.yaml +31 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/__init__.py +12 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/_init.py +76 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/built_in_cmds/__init__.py +0 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/built_in_cmds/_ut.py +117 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/built_in_cmds/context.py +92 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/built_in_cmds/profile.py +156 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/cli_options.py +135 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/cli_processor.py +257 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/cmd_util.py +88 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/config.py +21 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/context.py +116 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/data_util.py +461 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/dispatcher.py +84 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/extension.py +32 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/fn_util.py +61 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/fstore.py +273 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/jsondot.py +341 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/logger.py +220 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/profile.py +268 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/profile_store.py +35 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/recent.py +116 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/state.py +42 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/telemetry.py +150 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/template_util.py +26 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/timeutil.py +11 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/util.py +482 -0
- zen_cli-0.1.4/src/zen_cli/ctxp/var_template.py +109 -0
- zen_cli-0.1.4/src/zen_cli/mcp/__init__.py +3 -0
- zen_cli-0.1.4/src/zen_cli/mcp/_util.py +41 -0
- zen_cli-0.1.4/src/zen_cli/mcp/resources/__init__.py +33 -0
- zen_cli-0.1.4/src/zen_cli/mcp/resources/activity.py +60 -0
- zen_cli-0.1.4/src/zen_cli/mcp/resources/api.py +53 -0
- zen_cli-0.1.4/src/zen_cli/mcp/resources/credential.py +18 -0
- zen_cli-0.1.4/src/zen_cli/mcp/resources/deployment.py +14 -0
- zen_cli-0.1.4/src/zen_cli/mcp/resources/entitlement.py +21 -0
- zen_cli-0.1.4/src/zen_cli/mcp/resources/group.py +24 -0
- zen_cli-0.1.4/src/zen_cli/mcp/resources/network.py +21 -0
- zen_cli-0.1.4/src/zen_cli/mcp/resources/notification.py +40 -0
- zen_cli-0.1.4/src/zen_cli/mcp/resources/org.py +21 -0
- zen_cli-0.1.4/src/zen_cli/mcp/resources/pool.py +30 -0
- zen_cli-0.1.4/src/zen_cli/mcp/resources/provider.py +29 -0
- zen_cli-0.1.4/src/zen_cli/mcp/resources/sag.py +19 -0
- zen_cli-0.1.4/src/zen_cli/mcp/resources/task.py +63 -0
- zen_cli-0.1.4/src/zen_cli/mcp/resources/vm.py +34 -0
- zen_cli-0.1.4/src/zen_cli/mcp/server.py +72 -0
- zen_cli-0.1.4/src/zen_cli/service/__init__.py +0 -0
- zen_cli-0.1.4/src/zen_cli/service/activity.py +52 -0
- zen_cli-0.1.4/src/zen_cli/service/api.py +198 -0
- zen_cli-0.1.4/src/zen_cli/service/broker/__init__.py +2 -0
- zen_cli-0.1.4/src/zen_cli/service/broker/entitlement.py +21 -0
- zen_cli-0.1.4/src/zen_cli/service/broker/pool_group.py +24 -0
- zen_cli-0.1.4/src/zen_cli/service/cockpit/__init__.py +3 -0
- zen_cli-0.1.4/src/zen_cli/service/cockpit/network.py +24 -0
- zen_cli-0.1.4/src/zen_cli/service/cockpit/pool.py +24 -0
- zen_cli-0.1.4/src/zen_cli/service/cockpit/provider.py +21 -0
- zen_cli-0.1.4/src/zen_cli/service/cockpit/sag.py +24 -0
- zen_cli-0.1.4/src/zen_cli/service/cockpit/vm.py +110 -0
- zen_cli-0.1.4/src/zen_cli/service/credential.py +21 -0
- zen_cli-0.1.4/src/zen_cli/service/deployment.py +45 -0
- zen_cli-0.1.4/src/zen_cli/service/notification.py +44 -0
- zen_cli-0.1.4/src/zen_cli/service/org.py +32 -0
- zen_cli-0.1.4/src/zen_cli/service/task.py +381 -0
- zen_cli-0.1.4/src/zen_cli/sglib/__init__.py +3 -0
- zen_cli-0.1.4/src/zen_cli/sglib/auth.py +346 -0
- zen_cli-0.1.4/src/zen_cli/sglib/cli_options.py +63 -0
- zen_cli-0.1.4/src/zen_cli/sglib/client_util.py +490 -0
- zen_cli-0.1.4/src/zen_cli/sglib/csp.py +199 -0
- zen_cli-0.1.4/src/zen_cli/sglib/ez_client.py +348 -0
- zen_cli-0.1.4/src/zen_cli/sglib/init.py +18 -0
- zen_cli-0.1.4/src/zen_cli/sglib/login_support.py +333 -0
- zen_cli-0.1.4/src/zen_cli/sglib/mdc.py +19 -0
- zen_cli-0.1.4/src/zen_cli/sglib/payload_util.py +29 -0
- zen_cli-0.1.4/src/zen_cli/sglib/requtil.py +40 -0
- zen_cli-0.1.4/src/zen_cli/sglib/utils.py +107 -0
- zen_cli-0.1.4/src/zen_cli/sglib/zds_client.py +8 -0
- zen_cli-0.1.4/src/zen_cli/support/auth.py +63 -0
- zen_cli-0.1.4/src/zen_cli/support/payload.py +123 -0
- zen_cli-0.1.4/src/zen_cli/support/profile.py +49 -0
- zen_cli-0.1.4/src/zen_cli/support/task.py +312 -0
- zen_cli-0.1.4/src/zen_cli/support/use_util.py +103 -0
- zen_cli-0.1.4/src/zen_cli/support/vm.py +8 -0
- zen_cli-0.1.4/src/zen_cli/util/exec_util.py +263 -0
- zen_cli-0.1.4/src/zen_cli/util/exit.py +17 -0
- zen_cli-0.1.4/src/zen_cli/util/param_util.py +39 -0
- zen_cli-0.1.4/src/zen_cli/util/patch_util.py +38 -0
- zen_cli-0.1.4/src/zen_cli/util/query_util.py +98 -0
- zen_cli-0.1.4/src/zen_cli/util/readonly.py +8 -0
- zen_cli-0.1.4/src/zen_cli/util/versions.py +65 -0
- zen_cli-0.1.4/tests/test_auth_status.py +26 -0
- zen_cli-0.1.4/tests/test_cli.py +151 -0
- zen_cli-0.1.4/tests/test_device_login.py +132 -0
- zen_cli-0.1.4/tests/test_mcp.py +78 -0
- zen_cli-0.1.4/tests/test_payload.py +57 -0
- zen_cli-0.1.1/PKG-INFO +0 -57
- zen_cli-0.1.1/README.md +0 -37
- zen_cli-0.1.1/pyproject.toml +0 -40
- zen_cli-0.1.1/src/zen_cli/__init__.py +0 -1
- zen_cli-0.1.1/src/zen_cli/__main__.py +0 -4
- zen_cli-0.1.1/src/zen_cli/cli.py +0 -12
- zen_cli-0.1.1/src/zen_cli/commands/__init__.py +0 -1
- zen_cli-0.1.1/src/zen_cli/commands/hello.py +0 -7
- zen_cli-0.1.1/tests/test_cli.py +0 -24
- {zen_cli-0.1.1 → zen_cli-0.1.4}/LICENSE +0 -0
zen_cli-0.1.4/PKG-INFO
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: zen-cli
|
|
3
|
+
Version: 0.1.4
|
|
4
|
+
Summary: Command-line toolbox for Zen Cloud PC. Operate orgs, pools, VMs, and tasks; call ZDS APIs; expose a stdio MCP server.
|
|
5
|
+
Project-URL: Homepage, https://pypi.org/project/zen-cli/
|
|
6
|
+
Author: zen-cli authors
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Python: >=3.12
|
|
10
|
+
Requires-Dist: authlib
|
|
11
|
+
Requires-Dist: click>=8.1
|
|
12
|
+
Requires-Dist: coloredlogs
|
|
13
|
+
Requires-Dist: httpx2
|
|
14
|
+
Requires-Dist: mcp>=2
|
|
15
|
+
Requires-Dist: portalocker[win32]
|
|
16
|
+
Requires-Dist: pydantic
|
|
17
|
+
Requires-Dist: pyjwt
|
|
18
|
+
Requires-Dist: python-dotenv
|
|
19
|
+
Requires-Dist: pyyaml
|
|
20
|
+
Requires-Dist: questionary
|
|
21
|
+
Requires-Dist: tabulate
|
|
22
|
+
Requires-Dist: yumako
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: build; extra == 'dev'
|
|
25
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
26
|
+
Requires-Dist: pre-commit; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
28
|
+
Provides-Extra: release
|
|
29
|
+
Requires-Dist: build; extra == 'release'
|
|
30
|
+
Requires-Dist: twine; extra == 'release'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# zen-cli
|
|
34
|
+
|
|
35
|
+
[](https://pypi.org/project/zen-cli/) [](https://www.python.org/downloads/) [](LICENSE) [](https://pypi.org/project/zen-cli/) [](https://pypi.org/project/zen-cli/) [](https://pypi.org/project/zen-cli/) [](https://github.com/astral-sh/ruff) [](https://mypy-lang.org/) [](https://click.palletsprojects.com/) [](https://github.com/pypa/hatch)
|
|
36
|
+
|
|
37
|
+
Command-line toolbox for Zen Cloud PC, designed for AI and human.
|
|
38
|
+
|
|
39
|
+
## Contents
|
|
40
|
+
|
|
41
|
+
- [Try it out](#try-it-out)
|
|
42
|
+
- [Prerequisites](#prerequisites)
|
|
43
|
+
- [Installation](#installation)
|
|
44
|
+
- [Mac & Linux](#mac--linux)
|
|
45
|
+
- [Windows](#windows)
|
|
46
|
+
- [Use the CLI](#use-the-cli)
|
|
47
|
+
- [Documentation](#documentation)
|
|
48
|
+
- [License](#license)
|
|
49
|
+
|
|
50
|
+
## Try it out
|
|
51
|
+
|
|
52
|
+
### Prerequisites
|
|
53
|
+
|
|
54
|
+
* Python 3.12 or newer
|
|
55
|
+
* Pip
|
|
56
|
+
|
|
57
|
+
### Installation
|
|
58
|
+
|
|
59
|
+
#### Mac & Linux
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
pip install zen-cli
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
#### Windows
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
pip install zen-cli
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
If Python was installed without “Add python to PATH”, add Python and its `Scripts` directory to PATH.
|
|
72
|
+
|
|
73
|
+
### Use the CLI
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
zen login
|
|
77
|
+
zen auth status
|
|
78
|
+
zen auth details
|
|
79
|
+
zen auth token
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`zen login` reuses a valid cached token or configured credentials (API token, client id/secret). If neither is available it starts device-code login. It does not print the access token. Machine login is `zen login --client-id` / `--client-secret`. `zen auth status` is JSON (`logged_in`, `method`, `ttl`). `zen auth details` is the JWT and org. `zen auth token` is the bearer (`--service` on details/token). `zen auth refresh` refreshes the cached token.
|
|
83
|
+
|
|
84
|
+
Run a command, for example, list pools:
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
zen pool list
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Documentation
|
|
91
|
+
|
|
92
|
+
* [User guide](docs/user-guide.md) — profiles, flags, payloads, and command conventions
|
|
93
|
+
* [Cheatsheet](docs/cheatsheet.md) — command examples
|
|
94
|
+
* [Developer guide](docs/dev.md) — build, test, and package layout
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
Licensed under the MIT License. See [LICENSE](LICENSE).
|
zen_cli-0.1.4/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# zen-cli
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/zen-cli/) [](https://www.python.org/downloads/) [](LICENSE) [](https://pypi.org/project/zen-cli/) [](https://pypi.org/project/zen-cli/) [](https://pypi.org/project/zen-cli/) [](https://github.com/astral-sh/ruff) [](https://mypy-lang.org/) [](https://click.palletsprojects.com/) [](https://github.com/pypa/hatch)
|
|
4
|
+
|
|
5
|
+
Command-line toolbox for Zen Cloud PC, designed for AI and human.
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- [Try it out](#try-it-out)
|
|
10
|
+
- [Prerequisites](#prerequisites)
|
|
11
|
+
- [Installation](#installation)
|
|
12
|
+
- [Mac & Linux](#mac--linux)
|
|
13
|
+
- [Windows](#windows)
|
|
14
|
+
- [Use the CLI](#use-the-cli)
|
|
15
|
+
- [Documentation](#documentation)
|
|
16
|
+
- [License](#license)
|
|
17
|
+
|
|
18
|
+
## Try it out
|
|
19
|
+
|
|
20
|
+
### Prerequisites
|
|
21
|
+
|
|
22
|
+
* Python 3.12 or newer
|
|
23
|
+
* Pip
|
|
24
|
+
|
|
25
|
+
### Installation
|
|
26
|
+
|
|
27
|
+
#### Mac & Linux
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
pip install zen-cli
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
#### Windows
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
pip install zen-cli
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
If Python was installed without “Add python to PATH”, add Python and its `Scripts` directory to PATH.
|
|
40
|
+
|
|
41
|
+
### Use the CLI
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
zen login
|
|
45
|
+
zen auth status
|
|
46
|
+
zen auth details
|
|
47
|
+
zen auth token
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`zen login` reuses a valid cached token or configured credentials (API token, client id/secret). If neither is available it starts device-code login. It does not print the access token. Machine login is `zen login --client-id` / `--client-secret`. `zen auth status` is JSON (`logged_in`, `method`, `ttl`). `zen auth details` is the JWT and org. `zen auth token` is the bearer (`--service` on details/token). `zen auth refresh` refreshes the cached token.
|
|
51
|
+
|
|
52
|
+
Run a command, for example, list pools:
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
zen pool list
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Documentation
|
|
59
|
+
|
|
60
|
+
* [User guide](docs/user-guide.md) — profiles, flags, payloads, and command conventions
|
|
61
|
+
* [Cheatsheet](docs/cheatsheet.md) — command examples
|
|
62
|
+
* [Developer guide](docs/dev.md) — build, test, and package layout
|
|
63
|
+
|
|
64
|
+
## License
|
|
65
|
+
|
|
66
|
+
Licensed under the MIT License. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.26"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "zen-cli"
|
|
7
|
+
version = "0.1.4"
|
|
8
|
+
description = "Command-line toolbox for Zen Cloud PC. Operate orgs, pools, VMs, and tasks; call ZDS APIs; expose a stdio MCP server."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
requires-python = ">=3.12"
|
|
13
|
+
authors = [{ name = "zen-cli authors" }]
|
|
14
|
+
dependencies = [
|
|
15
|
+
"authlib",
|
|
16
|
+
"click>=8.1",
|
|
17
|
+
"coloredlogs",
|
|
18
|
+
"httpx2",
|
|
19
|
+
"mcp>=2",
|
|
20
|
+
"python-dotenv",
|
|
21
|
+
"pydantic",
|
|
22
|
+
"portalocker[win32]",
|
|
23
|
+
"PyJWT",
|
|
24
|
+
"pyyaml",
|
|
25
|
+
"questionary",
|
|
26
|
+
"tabulate",
|
|
27
|
+
"yumako",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
dev = ["build", "pre-commit", "ruff", "mypy"]
|
|
32
|
+
release = ["build", "twine"]
|
|
33
|
+
|
|
34
|
+
[project.scripts]
|
|
35
|
+
zen = "zen_cli.cli:main"
|
|
36
|
+
|
|
37
|
+
[project.urls]
|
|
38
|
+
Homepage = "https://pypi.org/project/zen-cli/"
|
|
39
|
+
|
|
40
|
+
[tool.hatch.build.targets.sdist]
|
|
41
|
+
include = ["src/zen_cli", "tests", "README.md", "LICENSE"]
|
|
42
|
+
|
|
43
|
+
[tool.ruff]
|
|
44
|
+
target-version = "py312"
|
|
45
|
+
line-length = 120
|
|
46
|
+
src = ["src"]
|
|
47
|
+
exclude = ["cli-ref"]
|
|
48
|
+
|
|
49
|
+
[tool.ruff.lint]
|
|
50
|
+
select = ["E", "F", "I", "UP", "B", "SIM", "RUF"]
|
|
51
|
+
|
|
52
|
+
[tool.mypy]
|
|
53
|
+
python_version = "3.12"
|
|
54
|
+
strict = true
|
|
55
|
+
files = ["src"]
|
|
56
|
+
|
|
57
|
+
[[tool.mypy.overrides]]
|
|
58
|
+
module = ["mcp", "mcp.*"]
|
|
59
|
+
ignore_missing_imports = true
|
|
60
|
+
|
|
61
|
+
[[tool.mypy.overrides]]
|
|
62
|
+
module = [
|
|
63
|
+
"yumako",
|
|
64
|
+
"yumako.*",
|
|
65
|
+
"authlib",
|
|
66
|
+
"authlib.*",
|
|
67
|
+
"yaml",
|
|
68
|
+
"httpx2",
|
|
69
|
+
"httpx2.*",
|
|
70
|
+
]
|
|
71
|
+
ignore_missing_imports = true
|
|
72
|
+
|
|
73
|
+
[[tool.mypy.overrides]]
|
|
74
|
+
module = ["zen_cli.cmds", "zen_cli.cmds.*", "zen_cli.ctxp", "zen_cli.ctxp.*"]
|
|
75
|
+
disallow_untyped_decorators = false
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
from dotenv import load_dotenv
|
|
9
|
+
from yumako import env
|
|
10
|
+
|
|
11
|
+
import zen_cli.ctxp as ctxp
|
|
12
|
+
from zen_cli.ctxp.cli_processor import register_commands
|
|
13
|
+
|
|
14
|
+
_PACKAGE_DIR = Path(__file__).resolve().parent
|
|
15
|
+
_COMMANDS_DIR = _PACKAGE_DIR / "cmds"
|
|
16
|
+
_CONFIG_DIR = _PACKAGE_DIR / "config"
|
|
17
|
+
_commands_loaded = False
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# -----------------------------------------------------------
|
|
21
|
+
import zen_cli.ctxp.logger as logger # noqa: E402
|
|
22
|
+
|
|
23
|
+
logger.setup()
|
|
24
|
+
logging.getLogger("charset_normalizer").setLevel(logging.WARN)
|
|
25
|
+
logging.getLogger("csp").setLevel(logging.INFO)
|
|
26
|
+
logging.getLogger("context").setLevel(logging.WARN)
|
|
27
|
+
logging.getLogger("init").setLevel(logging.WARN)
|
|
28
|
+
logging.getLogger("profile").setLevel(logging.WARN)
|
|
29
|
+
logging.getLogger("httpx").setLevel(logging.WARN)
|
|
30
|
+
logging.getLogger("httpx2").setLevel(logging.WARN)
|
|
31
|
+
logging.getLogger("urllib3").setLevel(logging.ERROR)
|
|
32
|
+
# logging.getLogger("zen_cli.sglib.login_support").setLevel(logging.DEBUG)
|
|
33
|
+
# logging.getLogger("login_support").setLevel(logging.DEBUG)
|
|
34
|
+
# -----------------------------------------------------------
|
|
35
|
+
import zen_cli.sglib.ez_client as ez_client # noqa: E402
|
|
36
|
+
|
|
37
|
+
ez_client._print_http_error = False
|
|
38
|
+
|
|
39
|
+
CONTEXT_SETTINGS = {
|
|
40
|
+
"help_option_names": ["-h", "--help"],
|
|
41
|
+
"max_content_width": 160,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _apply_readonly() -> None:
|
|
46
|
+
data = ctxp.profile.current(exit_on_failure=False)
|
|
47
|
+
if not data:
|
|
48
|
+
return
|
|
49
|
+
is_readonly = data.get("readonly")
|
|
50
|
+
if isinstance(is_readonly, str):
|
|
51
|
+
is_readonly = is_readonly.strip().lower() in ("1", "true", "yes")
|
|
52
|
+
else:
|
|
53
|
+
is_readonly = bool(is_readonly)
|
|
54
|
+
if is_readonly:
|
|
55
|
+
from zen_cli.util import readonly as readonly_support
|
|
56
|
+
|
|
57
|
+
ez_client.set_readonly(True, readonly_support.ALLOW_PATHS)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _enable_verbose() -> None:
|
|
61
|
+
root = logging.getLogger()
|
|
62
|
+
root.setLevel(logging.DEBUG)
|
|
63
|
+
for handler in root.handlers:
|
|
64
|
+
handler.setLevel(logging.DEBUG)
|
|
65
|
+
for name in (
|
|
66
|
+
"zen_cli",
|
|
67
|
+
"csp",
|
|
68
|
+
"profile",
|
|
69
|
+
"httpx",
|
|
70
|
+
"httpx2",
|
|
71
|
+
"httpcore",
|
|
72
|
+
"authlib",
|
|
73
|
+
):
|
|
74
|
+
logging.getLogger(name).setLevel(logging.DEBUG)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _check_upgrade() -> None:
|
|
78
|
+
check_flag_from_env = env.bool("HCS_CLI_CHECK_UPGRADE", True)
|
|
79
|
+
if not check_flag_from_env:
|
|
80
|
+
return
|
|
81
|
+
if os.environ.get("_ZEN_COMPLETE"):
|
|
82
|
+
return
|
|
83
|
+
if len(sys.argv) > 1 and sys.argv[1] in ("upgrade", "mcp", "completion"):
|
|
84
|
+
return
|
|
85
|
+
from zen_cli.util.versions import check_upgrade
|
|
86
|
+
|
|
87
|
+
check_upgrade()
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@click.group(name="zen", context_settings=CONTEXT_SETTINGS)
|
|
91
|
+
@click.version_option(package_name="zen-cli", prog_name="zen")
|
|
92
|
+
@click.option(
|
|
93
|
+
"--profile",
|
|
94
|
+
"-p",
|
|
95
|
+
type=str,
|
|
96
|
+
required=False,
|
|
97
|
+
help="Specify the profile to use. Optional.",
|
|
98
|
+
)
|
|
99
|
+
@click.option(
|
|
100
|
+
"--mdc",
|
|
101
|
+
type=str,
|
|
102
|
+
required=False,
|
|
103
|
+
help=("MDC name from profile zds.mdcs (e.g. beijing, singapore). Default is the first zds.mdcs entry."),
|
|
104
|
+
)
|
|
105
|
+
@click.option(
|
|
106
|
+
"--check-upgrade/--no-check-upgrade",
|
|
107
|
+
default=None,
|
|
108
|
+
help="Check for a new zen-cli version. On by default. Or set HCS_CLI_CHECK_UPGRADE=false.",
|
|
109
|
+
)
|
|
110
|
+
@click.option(
|
|
111
|
+
"--telemetry/--no-telemetry",
|
|
112
|
+
default=None,
|
|
113
|
+
help="Send command telemetry. Off by default. Or set ZEN_CLI_TELEMETRY=true.",
|
|
114
|
+
)
|
|
115
|
+
@click.option(
|
|
116
|
+
"--verbose",
|
|
117
|
+
"-v",
|
|
118
|
+
is_flag=True,
|
|
119
|
+
default=False,
|
|
120
|
+
help="Print debug logs, including HTTP method and URL.",
|
|
121
|
+
)
|
|
122
|
+
def cli(
|
|
123
|
+
profile: str,
|
|
124
|
+
mdc: str,
|
|
125
|
+
check_upgrade: bool | None,
|
|
126
|
+
telemetry: bool | None,
|
|
127
|
+
verbose: bool,
|
|
128
|
+
**kwargs: Any,
|
|
129
|
+
) -> None:
|
|
130
|
+
"""zen command-line interface."""
|
|
131
|
+
if verbose:
|
|
132
|
+
_enable_verbose()
|
|
133
|
+
|
|
134
|
+
if check_upgrade is not False:
|
|
135
|
+
_check_upgrade()
|
|
136
|
+
|
|
137
|
+
if telemetry is True:
|
|
138
|
+
ctxp.telemetry.enable()
|
|
139
|
+
elif telemetry is False:
|
|
140
|
+
ctxp.telemetry.disable()
|
|
141
|
+
|
|
142
|
+
if profile:
|
|
143
|
+
ctxp.profile.activate(profile, persist=False)
|
|
144
|
+
|
|
145
|
+
from zen_cli.ctxp._init import _initialized_app_name
|
|
146
|
+
|
|
147
|
+
if not _initialized_app_name:
|
|
148
|
+
return
|
|
149
|
+
from zen_cli.support import profile as profile_support
|
|
150
|
+
|
|
151
|
+
profile_support.ensure_standard_profiles(interactive=False)
|
|
152
|
+
|
|
153
|
+
if mdc:
|
|
154
|
+
from zen_cli.sglib import mdc as mdc_session
|
|
155
|
+
|
|
156
|
+
mdc_session.set(mdc)
|
|
157
|
+
|
|
158
|
+
_apply_readonly()
|
|
159
|
+
load_commands()
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def load_commands() -> None:
|
|
163
|
+
"""Attach built-in and cmds/ commands without running Click."""
|
|
164
|
+
global _commands_loaded
|
|
165
|
+
if _commands_loaded:
|
|
166
|
+
return
|
|
167
|
+
register_commands(cli, str(_COMMANDS_DIR))
|
|
168
|
+
_commands_loaded = True
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def main() -> None:
|
|
172
|
+
ctxp.init(app_name="zen", config_path=str(_CONFIG_DIR))
|
|
173
|
+
load_dotenv(".env")
|
|
174
|
+
if os.environ.get("_ZEN_COMPLETE"):
|
|
175
|
+
ctxp.telemetry.disable()
|
|
176
|
+
ctxp.init_cli(main_cli=cli, commands_dir=str(_COMMANDS_DIR))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
help = "System activity commands."
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
import zen_cli.sglib.cli_options as cli
|
|
6
|
+
from zen_cli.ctxp import recent
|
|
7
|
+
from zen_cli.service import activity
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.command()
|
|
11
|
+
@cli.org_id
|
|
12
|
+
@click.argument("id", type=str, required=False)
|
|
13
|
+
def get(org: str, id: str) -> Any:
|
|
14
|
+
"""Get a system activity by ID. Without an argument, use the recent activity."""
|
|
15
|
+
id = recent.require("activity", id)
|
|
16
|
+
org_id = None if org == "all" else cli.get_org_id(org)
|
|
17
|
+
ret = activity.get(id, org_id=org_id)
|
|
18
|
+
if ret:
|
|
19
|
+
return ret
|
|
20
|
+
return "", 1
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
import zen_cli.sglib.cli_options as cli
|
|
6
|
+
from zen_cli.ctxp import recent, util
|
|
7
|
+
from zen_cli.service import activity
|
|
8
|
+
|
|
9
|
+
_RESOURCE_TYPES = [
|
|
10
|
+
"ORG",
|
|
11
|
+
"ORG_PREFERENCE",
|
|
12
|
+
"DATACENTER",
|
|
13
|
+
"POOL",
|
|
14
|
+
"ENTITLEMENT",
|
|
15
|
+
"VM",
|
|
16
|
+
"EDGE",
|
|
17
|
+
"SAG",
|
|
18
|
+
"TASK",
|
|
19
|
+
"PROVIDER_INSTANCE",
|
|
20
|
+
"NET_INFRA",
|
|
21
|
+
"EXPRESS_DEPLOYMENT",
|
|
22
|
+
"POOL_GROUP",
|
|
23
|
+
"IMAGE",
|
|
24
|
+
"SITE",
|
|
25
|
+
"SPEC",
|
|
26
|
+
"SESSION",
|
|
27
|
+
"VMAGENT",
|
|
28
|
+
"NOTIFICATION",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
_TABLE_MAPPING = {
|
|
32
|
+
"code": "Code",
|
|
33
|
+
"severity": "Severity",
|
|
34
|
+
"initiator": "Initiator",
|
|
35
|
+
"serviceName": "Service",
|
|
36
|
+
"resourceId": "Resource",
|
|
37
|
+
"traceId": "Trace",
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _format_activity_table(data: Any) -> Any:
|
|
42
|
+
for d in data:
|
|
43
|
+
if d.get("timestamp") and not d.get("createdAt"):
|
|
44
|
+
d["createdAt"] = d["timestamp"]
|
|
45
|
+
if not d.get("name"):
|
|
46
|
+
d["name"] = d.get("resourceName") or d.get("code") or ""
|
|
47
|
+
if not d.get("type"):
|
|
48
|
+
d["type"] = d.get("resourceType")
|
|
49
|
+
return util.default_table_formatter(data, _TABLE_MAPPING)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@click.command(name="list")
|
|
53
|
+
@cli.org_id
|
|
54
|
+
@click.option("--service-name", type=str, required=False, help="Filter by service name.")
|
|
55
|
+
@click.option("--code", type=str, required=False, help="Filter by activity code.")
|
|
56
|
+
@click.option("--trace-id", type=str, required=False, help="Filter by trace ID.")
|
|
57
|
+
@click.option("--span-id", type=str, required=False, help="Filter by span ID.")
|
|
58
|
+
@click.option("--resource-id", type=str, required=False, help="Filter by resource ID.")
|
|
59
|
+
@click.option("--resource-name", type=str, required=False, help="Filter by resource name.")
|
|
60
|
+
@click.option("--task-id", type=str, required=False, help="Filter by task ID.")
|
|
61
|
+
@click.option("--parent-id", type=str, required=False, help="Filter by parent activity ID.")
|
|
62
|
+
@click.option("--initiator", type=str, required=False, help="Filter by initiator.")
|
|
63
|
+
@click.option(
|
|
64
|
+
"--initiator-type",
|
|
65
|
+
type=click.Choice(["SYSTEM", "OPS", "CUSTOMER_ADMIN", "USER"], case_sensitive=False),
|
|
66
|
+
required=False,
|
|
67
|
+
help="Filter by initiator type.",
|
|
68
|
+
)
|
|
69
|
+
@click.option(
|
|
70
|
+
"--resource-type",
|
|
71
|
+
type=click.Choice(_RESOURCE_TYPES, case_sensitive=False),
|
|
72
|
+
required=False,
|
|
73
|
+
help="Filter by resource type.",
|
|
74
|
+
)
|
|
75
|
+
@click.option(
|
|
76
|
+
"--severity",
|
|
77
|
+
type=click.Choice(["CRITICAL", "WARNING", "INFO", "TRIVIAL"], case_sensitive=False),
|
|
78
|
+
required=False,
|
|
79
|
+
help="Filter by severity.",
|
|
80
|
+
)
|
|
81
|
+
@click.option(
|
|
82
|
+
"--status",
|
|
83
|
+
type=click.Choice(
|
|
84
|
+
["QUEUED", "START", "PROGRESS", "SUCCESS", "ERROR", "CANCELLED"],
|
|
85
|
+
case_sensitive=False,
|
|
86
|
+
),
|
|
87
|
+
required=False,
|
|
88
|
+
help="Filter by status.",
|
|
89
|
+
)
|
|
90
|
+
@click.option(
|
|
91
|
+
"--timestamp-from",
|
|
92
|
+
type=str,
|
|
93
|
+
required=False,
|
|
94
|
+
help="Inclusive lower bound (ISO-8601).",
|
|
95
|
+
)
|
|
96
|
+
@click.option(
|
|
97
|
+
"--timestamp-to",
|
|
98
|
+
type=str,
|
|
99
|
+
required=False,
|
|
100
|
+
help="Inclusive upper bound (ISO-8601).",
|
|
101
|
+
)
|
|
102
|
+
@cli.sort
|
|
103
|
+
@cli.limit
|
|
104
|
+
@cli.formatter(_format_activity_table)
|
|
105
|
+
def list_activities(
|
|
106
|
+
org: str,
|
|
107
|
+
service_name: str,
|
|
108
|
+
code: str,
|
|
109
|
+
trace_id: str,
|
|
110
|
+
span_id: str,
|
|
111
|
+
resource_id: str,
|
|
112
|
+
resource_name: str,
|
|
113
|
+
task_id: str,
|
|
114
|
+
parent_id: str,
|
|
115
|
+
initiator: str,
|
|
116
|
+
initiator_type: str,
|
|
117
|
+
resource_type: str,
|
|
118
|
+
severity: str,
|
|
119
|
+
status: str,
|
|
120
|
+
timestamp_from: str,
|
|
121
|
+
timestamp_to: str,
|
|
122
|
+
sort: str,
|
|
123
|
+
limit: int,
|
|
124
|
+
) -> Any:
|
|
125
|
+
"""List system activities."""
|
|
126
|
+
org_id = None if org == "all" else cli.get_org_id(org)
|
|
127
|
+
if initiator_type:
|
|
128
|
+
initiator_type = initiator_type.upper()
|
|
129
|
+
if resource_type:
|
|
130
|
+
resource_type = resource_type.upper()
|
|
131
|
+
if severity:
|
|
132
|
+
severity = severity.upper()
|
|
133
|
+
if status:
|
|
134
|
+
status = status.upper()
|
|
135
|
+
|
|
136
|
+
ret = activity.list(
|
|
137
|
+
org_id=org_id,
|
|
138
|
+
service_name=service_name,
|
|
139
|
+
code=code,
|
|
140
|
+
trace_id=trace_id,
|
|
141
|
+
span_id=span_id,
|
|
142
|
+
resource_id=resource_id,
|
|
143
|
+
resource_name=resource_name,
|
|
144
|
+
task_id=task_id,
|
|
145
|
+
parent_id=parent_id,
|
|
146
|
+
initiator=initiator,
|
|
147
|
+
initiator_type=initiator_type,
|
|
148
|
+
resource_type=resource_type,
|
|
149
|
+
severity=severity,
|
|
150
|
+
status=status,
|
|
151
|
+
timestamp_from=timestamp_from,
|
|
152
|
+
timestamp_to=timestamp_to,
|
|
153
|
+
sort=sort,
|
|
154
|
+
limit=limit,
|
|
155
|
+
)
|
|
156
|
+
recent.helper.default_list(ret, "activity")
|
|
157
|
+
return ret
|