noc-ops 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.

Potentially problematic release.


This version of noc-ops might be problematic. Click here for more details.

Files changed (53) hide show
  1. noc_ops-0.1.0/.gitignore +39 -0
  2. noc_ops-0.1.0/LICENSE +201 -0
  3. noc_ops-0.1.0/NOTICE +18 -0
  4. noc_ops-0.1.0/PKG-INFO +275 -0
  5. noc_ops-0.1.0/README.md +239 -0
  6. noc_ops-0.1.0/pyproject.toml +65 -0
  7. noc_ops-0.1.0/src/noc_ops/__init__.py +2 -0
  8. noc_ops-0.1.0/src/noc_ops/agent.py +486 -0
  9. noc_ops-0.1.0/src/noc_ops/assets/ops-config.default.toml +127 -0
  10. noc_ops-0.1.0/src/noc_ops/assets/runbooks/README.md +18 -0
  11. noc_ops-0.1.0/src/noc_ops/assets/runbooks/alb-access-log-decommission.md +53 -0
  12. noc_ops-0.1.0/src/noc_ops/assets/runbooks/certbot-renewal-troubleshooting.md +87 -0
  13. noc_ops-0.1.0/src/noc_ops/assets/runbooks/ec2-public-exposure-hardening.md +79 -0
  14. noc_ops-0.1.0/src/noc_ops/assets/runbooks/s3-bucket-usage-check.md +52 -0
  15. noc_ops-0.1.0/src/noc_ops/assets/runbooks/site-access-source-stats.md +75 -0
  16. noc_ops-0.1.0/src/noc_ops/aws_safety.py +404 -0
  17. noc_ops-0.1.0/src/noc_ops/cli.py +213 -0
  18. noc_ops-0.1.0/src/noc_ops/dashboard/__init__.py +1 -0
  19. noc_ops-0.1.0/src/noc_ops/dashboard/favicon.svg +4 -0
  20. noc_ops-0.1.0/src/noc_ops/dashboard/index.html +1091 -0
  21. noc_ops-0.1.0/src/noc_ops/dashboard/server.py +483 -0
  22. noc_ops-0.1.0/src/noc_ops/dashboard/vendor/ag-grid-community.min.js +14024 -0
  23. noc_ops-0.1.0/src/noc_ops/dashboard/vendor/fonts/inter-latin-wght-normal.woff2 +0 -0
  24. noc_ops-0.1.0/src/noc_ops/deploy_config.py +264 -0
  25. noc_ops-0.1.0/src/noc_ops/doctor.py +141 -0
  26. noc_ops-0.1.0/src/noc_ops/egress_probe.py +535 -0
  27. noc_ops-0.1.0/src/noc_ops/error_patterns.py +200 -0
  28. noc_ops-0.1.0/src/noc_ops/init_wizard.py +259 -0
  29. noc_ops-0.1.0/src/noc_ops/license.py +305 -0
  30. noc_ops-0.1.0/src/noc_ops/mcp_server.py +397 -0
  31. noc_ops-0.1.0/src/noc_ops/netprobe.py +183 -0
  32. noc_ops-0.1.0/src/noc_ops/ops_log.py +145 -0
  33. noc_ops-0.1.0/src/noc_ops/paths.py +110 -0
  34. noc_ops-0.1.0/src/noc_ops/providers/__init__.py +25 -0
  35. noc_ops-0.1.0/src/noc_ops/providers/aliyun.py +279 -0
  36. noc_ops-0.1.0/src/noc_ops/providers/aws.py +455 -0
  37. noc_ops-0.1.0/src/noc_ops/providers/azure.py +359 -0
  38. noc_ops-0.1.0/src/noc_ops/providers/base.py +122 -0
  39. noc_ops-0.1.0/src/noc_ops/providers/cloudflare.py +81 -0
  40. noc_ops-0.1.0/src/noc_ops/providers/gcp.py +365 -0
  41. noc_ops-0.1.0/src/noc_ops/providers/local.py +131 -0
  42. noc_ops-0.1.0/src/noc_ops/providers/oracle.py +290 -0
  43. noc_ops-0.1.0/src/noc_ops/providers/sangfor.py +396 -0
  44. noc_ops-0.1.0/src/noc_ops/providers/supabase.py +88 -0
  45. noc_ops-0.1.0/src/noc_ops/providers/synology.py +201 -0
  46. noc_ops-0.1.0/src/noc_ops/providers/tencent.py +184 -0
  47. noc_ops-0.1.0/src/noc_ops/providers/vmware.py +291 -0
  48. noc_ops-0.1.0/src/noc_ops/providers/volcengine.py +319 -0
  49. noc_ops-0.1.0/src/noc_ops/reboot_cli.py +197 -0
  50. noc_ops-0.1.0/src/noc_ops/schedule_ops.py +218 -0
  51. noc_ops-0.1.0/src/noc_ops/setup_clients.py +216 -0
  52. noc_ops-0.1.0/src/noc_ops/skill/SKILL.md.tmpl +63 -0
  53. noc_ops-0.1.0/src/noc_ops/sync.py +1572 -0
@@ -0,0 +1,39 @@
1
+ # 工作区运行时数据(sync 生成的看板数据 + 状态/快照/日志,含 IP/账号/命令,勿外泄)
2
+ /data.json
3
+ /local-servers.toml
4
+ /.state/
5
+
6
+ # 本地 Claude Code 设置(机器本地,不入库)
7
+ .claude/settings.local.json
8
+
9
+ # Python 打包/缓存
10
+ __pycache__/
11
+ *.pyc
12
+ .venv/
13
+ *.egg-info/
14
+ build/
15
+ dist/
16
+
17
+ # macOS
18
+ .DS_Store
19
+
20
+ # 混淆分发构建产物(PyArmor,由 scripts/build-obfuscated.sh 生成)
21
+ /build_obf/
22
+
23
+ # 测试夹具工作区:只保留匿名化的 ops-config.toml,其余运行时产物不入库
24
+ /tests/fixtures/workspace/.state/
25
+ /tests/fixtures/workspace/runbooks/
26
+ /tests/fixtures/workspace/data.json
27
+ /tests/fixtures/workspace/inventory.md
28
+ /tests/fixtures/workspace/local-servers.toml
29
+
30
+ # 工作区本体(仓根目录=作者的真实工作区):部署配置 / 清单 / 剧本都是机器特定数据,不入库
31
+ # 2026-10-25 起停止跟踪(此前被跟踪过,公开本仓前须 orphan 新仓重建历史)
32
+ /ops-config.toml
33
+ /inventory.md
34
+ /runbooks/
35
+ # 本机 Claude Code 项目级 MCP 配置与渠道能力目录(含个人路径)
36
+ /.mcp.json
37
+ /capabilities.toml
38
+ # 无关的飞书文档草稿缓存
39
+ /draft_*_folder/
noc_ops-0.1.0/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
noc_ops-0.1.0/NOTICE ADDED
@@ -0,0 +1,18 @@
1
+ noc-ops — 多云运维 ops CLI
2
+ Copyright 2026 Fenghuang
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+
16
+ Bundled third-party components (src/noc_ops/dashboard/vendor/):
17
+ - AG Grid Community — MIT License, Copyright (c) AG Grid Ltd
18
+ - Inter font — SIL Open Font License 1.1, Copyright (c) The Inter Project Authors
noc_ops-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,275 @@
1
+ Metadata-Version: 2.5
2
+ Name: noc-ops
3
+ Version: 0.1.0
4
+ Summary: 多云运维 ops CLI —— 9 朵云(AWS / 阿里云 / 腾讯云 / 火山引擎 / GCP / Azure / Oracle / Cloudflare / Supabase)+ 本地网络机器:清单同步、运维看板、定时重启、Claude Code / Codex skill;可选自然语言 agent 与 MCP
5
+ Project-URL: Homepage, https://github.com/pholex/noc-ops
6
+ Project-URL: Repository, https://github.com/pholex/noc-ops
7
+ Project-URL: Skill, https://github.com/pholex/multicloud-ops
8
+ Author: Fenghuang
9
+ License-Expression: Apache-2.0
10
+ License-File: LICENSE
11
+ License-File: NOTICE
12
+ Keywords: aliyun,aws,azure,claude-code,devops,gcp,multicloud,noc,oci,ops,skill,tencent-cloud
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: System Administrators
16
+ Classifier: Operating System :: MacOS
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Topic :: System :: Systems Administration
20
+ Requires-Python: >=3.10
21
+ Provides-Extra: agent
22
+ Requires-Dist: claude-agent-sdk<0.3,>=0.2.156; extra == 'agent'
23
+ Provides-Extra: all
24
+ Requires-Dist: claude-agent-sdk<0.3,>=0.2.156; extra == 'all'
25
+ Requires-Dist: mcp<3,>=2.2.0; extra == 'all'
26
+ Provides-Extra: dev
27
+ Requires-Dist: claude-agent-sdk<0.3,>=0.2.156; extra == 'dev'
28
+ Requires-Dist: mcp<3,>=2.2.0; extra == 'dev'
29
+ Requires-Dist: pytest>=8; extra == 'dev'
30
+ Requires-Dist: pyyaml; extra == 'dev'
31
+ Provides-Extra: mcp
32
+ Requires-Dist: mcp<3,>=2.2.0; extra == 'mcp'
33
+ Provides-Extra: sangfor
34
+ Requires-Dist: pycryptodome; extra == 'sangfor'
35
+ Description-Content-Type: text/markdown
36
+
37
+ # NOC — 多云运维 ops CLI
38
+
39
+ 用自然语言指令运维多云机群(AWS / 阿里云 / 腾讯云 / 火山引擎 / Google Cloud / Azure / Oracle,另只读纳管 Cloudflare / Supabase)的 `ops` CLI,基于 [Claude Agent SDK](https://code.claude.com/docs/en/agent-sdk/python)。
40
+ 一次安装就接好多个 LLM 客户端:**`ops` CLI 本体 + Claude Code skill + Codex MCP**,共享 `providers + sync + aws_safety + schedule_ops` 这套底座。
41
+ 能力随日常运维不断**沉淀**:每做一项新运维,就存成一个 runbook,攒一段时间后接管大部分日常工作。
42
+
43
+ ## 代码与工作区(分离)
44
+
45
+ **代码**(pip/uv 装进 venv,只读):
46
+ ```
47
+ src/noc_ops/
48
+ ├── cli.py # `ops` 入口:分发 sync/noc/doctor/setup,默认走 agent
49
+ ├── agent.py # 自然语言 agent(交互/一次性两种模式)
50
+ ├── sync.py # 扫实例/域名/RDS/S3/Lambda/CloudFront/IAM/AI 密钥(Bedrock key)/SQS·SNS·SES·EventBridge/成本/账务额度,生成 inventory+data.json+ssh config
51
+ ├── mcp_server.py # MCP server(`ops-mcp` 入口,给 Codex 等)
52
+ ├── schedule_ops.py # 计划任务(定时重启,EventBridge + Lambda 派发)
53
+ ├── aws_safety.py # 读/写操作分类器(权限闸门)
54
+ ├── ops_log.py # 操作日志(写操作审计流水)
55
+ ├── paths.py # 工作区路径解析(代码↔数据分离)
56
+ ├── doctor.py / setup_clients.py # 体检 / 多客户端一键安装
57
+ ├── providers/ # 多云驱动:base + aws/aliyun/tencent/volcengine/gcp/azure/oracle/cloudflare/supabase/synology/vmware/sangfor/local
58
+ ├── dashboard/ # 看板前端(server.py + index.html + 自托管 ag-Grid/字体)
59
+ ├── skill/SKILL.md.tmpl # Claude Code skill 模板(setup 时渲染安装)
60
+ └── assets/runbooks/ # 全新安装的种子 runbook
61
+ ```
62
+
63
+ **工作区**(可变数据,默认 `~/.noc`,可用 `NOC_HOME` 或 `ops setup --workspace` 指定):
64
+ ```
65
+ <workspace>/
66
+ ├── inventory.md # 实例+域名+账务额度清单(人读,sync 生成)
67
+ ├── data.json # 机读数据(sync 生成,看板/MCP 用)
68
+ ├── runbooks/*.md # 能力库(用户沉淀,随用增长;升级不丢)
69
+ └── .state/ # 运行时状态(ssh 用户缓存 / 快照 / 操作日志)
70
+ ```
71
+
72
+ ## 安装与运行
73
+
74
+ 支持 macOS / Linux(纯 Python 包)。一行装(推荐):`curl -fsSL https://<host>/install.sh | sh`(自动装 uv + 从 PyPI 装 + 接入客户端)。或手动:
75
+
76
+ ```bash
77
+ uv tool install noc-ops # 或 pipx install noc-ops;开发者:uv tool install <本仓路径>
78
+ uv tool install --force 'noc-ops[agent]' # 可选:终端自然语言 agent(需 ANTHROPIC_API_KEY)
79
+ uv tool install --force 'noc-ops[mcp]' # 可选:ops-mcp,仅无 shell 的 GUI 客户端(Claude Desktop)需要
80
+ ops setup [--workspace ~/Developer/noc] # 记工作区 + 经 `skills` CLI 把 skill 扇出到所有已装客户端(skill 优先)
81
+ ops init # 交互式生成配置(发现账号/区域/SSH key,免手编 TOML)
82
+ ops doctor --fix # 体检:云 CLI 依赖 / 凭证 / 工作区 / 客户端;--fix 自动修
83
+
84
+ ops "宁夏有几台 EC2 在运行" # 一次性指令(任意目录可跑)
85
+ ops # 进入交互模式(推荐:边做边沉淀)
86
+ ops sync # 同步实例清单 + SSH 配置(新增实例后跑)
87
+ ops sync --account=<账号> # 只刷某一个云账号(AWS 账号 ID / 阿里云 profile 名)
88
+ ops noc # 启动 NOC 运维看板(默认后台;status/stop/restart 管理)
89
+ ```
90
+
91
+ 前置:用到哪朵云就装好对应 CLI 并配好凭证(`aws` / `aliyun` / `tccli` / `ve` / `gcloud` / `az` / `oci`;`ops doctor` 会逐项检查,没装 CLI 的云 `ops sync` 自动跳过)。
92
+ 渠道 **skill 优先**;无 shell 的 GUI 客户端(如 Claude Desktop)才需 `ops setup --with-mcp`(外包 `npx add-mcp`,含 Claude Desktop)。
93
+
94
+ ## ops noc — NOC 运维看板
95
+
96
+ `ops noc` 启动本地服务(默认 `http://127.0.0.1:8765`),用 **ag-Grid**(社区版,MIT)密集表格
97
+ 呈现全部实例:状态灯、账号、区域(旗帜)、类型、IP、实例 ID(点击复制)、登录用户、直连/跳板/SSM(无密钥对的 AWS 实例视为仅 SSM Session Manager 可达,不配 SSH)。
98
+ 顶部标签页分类展示 **实例 / 域名 / 数据库 / 存储 / 函数 / CDN / IAM / AI 密钥 / 消息·事件 / 成本 / 计划任务 / 剧本 / 操作日志** 十三类;「剧本」页列出 `runbooks/` 全部剧本(标题/沉淀时间/是否写操作/触发意图),点剧本名即在新页打开其 markdown(`/runbook?name=<名>`,限定在 runbooks 目录内)。
99
+ 支持按账号/区域/状态筛选、关键字搜索、点表头排序、列宽拖拽/重排、每列筛选菜单、**导出 CSV**。
100
+ Quartz 主题跟随系统明暗。右上「刷新」触发一次 `ops sync`(重扫 AWS + 探测新机器)再重载。
101
+ 数据来自 `<workspace>/data.json`(由 `ops sync` 生成)。
102
+
103
+ > 账号级的**账务/额度**(`credits` 键:信用余额、免费额度到期、超额保护、预算告警)没有独立 tab——它是账号状态而非资源清单,渲染在 `inventory.md` 的「💳 云账务 / 额度」节,刷新用 `ops sync --kind=credits`。与「成本」tab 的分工:credits 是「还剩多少、超额会怎样」,billing 是「花了多少」的流水。
104
+
105
+ > 「AI 密钥」tab 只盘点**元数据**(限定到哪个 API、绑定的服务账号、客户端限制、创建时间),**永远不取密钥串**(不调 `get-key-string`,data.json / inventory 里不会出现 key 本体)。目前接了两朵云:GCP 的 Cloud API Keys(AI Studio 的 Gemini key 与 Vertex AI Express key 本质都是它,按 `apiTargets` 标成「Gemini API」/「Vertex AI」,只盘 AI 用途;无限制 key 标红,Google 已在封禁闲置的无限制 key;项目需启用 `apikeys.googleapis.com`)和 AWS 的 Bedrock 长期 API key(IAM 服务专用凭证,含 Claude Platform on AWS key;只盘全球区(`--all-users` 一次列全;中国区不支持该参数,直接跳过);短期 12h key 本地签出、不可列)。阿里云百炼 key 没有列表 OpenAPI,暂未纳管。刷新 `ops sync --kind=apikeys`。
106
+
107
+ ag-Grid 的 JS、Inter 字体均**本地自托管在 `src/noc_ops/dashboard/vendor/`、不走第三方 CDN**(遵全局规则);
108
+ 看板服务用 Python stdlib 起、运行期不拉外部包。
109
+ (注:这里说的是「看板运行期」的取舍——不是全工程教条。`ops setup` 装 skill 时会按需调用
110
+ `skills` CLI(`npx skills`,节点级工具)做多客户端扇出;用对的成熟工具优先于死守零依赖。)
111
+
112
+ **生命周期**:`ops noc` **默认后台守护启动**(detach,关终端不死,日志写 `<workspace>/.state/noc.log`),立即返回。
113
+ - `ops noc status` — 看在不在跑(PID / URL)
114
+ - `ops noc stop` — 停掉(只杀 noc 自己的监听进程,非 noc 占用仅告警)
115
+ - `ops noc restart` — 停旧启新
116
+ - `ops noc -f` — 前台跑(占终端、Ctrl+C 退出,调试用)
117
+
118
+ 选项:`ops noc --port 9000 --no-open`(可与上面组合)。
119
+
120
+ ## ops sync — 实例清单/SSH 配置同步
121
+
122
+ 新增或变更 EC2 后跑 `ops sync`,它会全量扫描、对比快照、报告 新增/变更/删除,并重新生成
123
+ `inventory.md` 与 `~/.ssh/config`(marker 段)。私钥按约定 `~/.ssh/<profile>/<KeyName>.pem`
124
+ 自动推导;登录用户名(ec2-user / ubuntu / centos)对未缓存实例自动探测一次并缓存(幂等,日常只探新机器)。
125
+
126
+ 不必每次都全量重扫,可按两个维度收窄(都是 patch 式合并写回 `data.json`,不整份覆盖):
127
+
128
+ ```bash
129
+ ops sync --kind=instances # 按资源类型收窄(看板「按 tab 单刷」),扫所有账号
130
+ ops sync --account=123456789012 # 按 AWS 账号收窄:只扫该账号(~25s vs 全量一两分钟)
131
+ ops sync --account=123456789012 --kind=instances # 两者组合:只刷该账号的实例(~3s)
132
+ ops sync --account=<aliyun-profile> # 阿里云账号也认(profile 名或账号 ID,~2s)
133
+ ops sync --probe=<实例名|ID> # 只探这一台 AWS 实例的 SSH 登录用户名并回写 config(零云 API,几秒)
134
+ ```
135
+
136
+ `--account=` 只重扫指定账号,同云其它账号 / 其它云的行原样沿用;`~/.ssh/config` 的托管段虽是整段
137
+ 重写,但沿用账号的 Host 会一并还原写回(产出与全账号刷新逐字节一致)。`inventory.md` 与实例快照
138
+ 是全量产物、两条收窄路径都不动它们。
139
+
140
+ 账号名按云解析:**AWS** 用账号 ID,**阿里云**用 CLI profile 名(如 `<profile>`)或账号 ID 都行。
141
+ 各云能按账号刷的资源类型不同(AWS 九类;阿里云 = 实例/存储/域名,即 provider 真会产出的),
142
+ 点名了该云没有的类型会直接拒绝并列出可用值。
143
+
144
+ 非公网机器(VMware / Sangfor HCI / 群晖 / 本地物理机)**不参与全量 sync**(连不上时不该被误判
145
+ "已删除"),按**网络域**分两条命令单刷,各有各的门控,互不覆盖:
146
+
147
+ ```bash
148
+ ops sync --local # 只刷内网机器(network=lan);门控 = local_net.probe 内网探针
149
+ ops sync --tailscale # 只刷 Tailscale 组网上的机器;门控 = `tailscale status`
150
+ ops sync --index # 只刷 runbooks/操作日志索引进 data.json(零网络,秒级)
151
+ ```
152
+
153
+ 网络域按端点地址自动推导(`100.64.0.0/10` 或 `*.ts.net` → tailscale,其余 → lan),
154
+ 账号里显式写 `network = "tailscale"` 可覆盖。两个域**故意不合并**——"连不上"的含义不同:
155
+ 内网看人在不在内网,Tailscale 看 tailscaled 跑没跑、对端节点是否 Online。详见
156
+ `runbooks/sync-inventory.md` 与 `src/noc_ops/netprobe.py`。
157
+ 账号在 `src/noc_ops/providers/aws.py` 的 `ACCOUNTS` 维护;别名前缀/跳板在 `src/noc_ops/sync.py` 的 `ALIAS_PREFIX`/`JUMPS`。详见 `runbooks/sync-inventory.md`。
158
+
159
+ 可选环境变量:`OPS_MODEL`(默认 `claude-sonnet-4-6`)。
160
+
161
+ ## ops reboot — 重启一台实例(公有云 + 本地 HCI 同一入口)
162
+
163
+ ```bash
164
+ ops reboot <实例名|ID> # 重启:按 cloud 自动选通道
165
+ ops reboot <实例名|ID> --status # 只查实时状态(只读),重启后隔 ~40 秒用它复查
166
+ ops reboot <实例名|ID> --dry-run # 只打印将要执行的命令
167
+ ```
168
+
169
+ 通道按 `cloud` 走 `Provider.reboot_argv`:AWS `aws ec2 reboot-instances`、腾讯 `RebootInstances`、
170
+ 阿里 `RebootInstance`、火山 `ecs RebootInstance`(优雅)、GCP `instances reset`(硬)、Azure `vm restart`、Oracle `SOFTRESET`,
171
+ **VMware 走 vCenter REST、深信服 HCI 走 SCP 管控 API**(两者都是 Token 认证 + Keychain 取密码,
172
+ CLI 拼不出来——这也是本命令存在的理由:以前只有 MCP server 接了这条通道,走 skill 的
173
+ Claude Code / Codex 够不着)。群晖 / ESXi 宿主 / Cloudflare / Supabase 没有管控 API,
174
+ 会**如实拒绝并给出该走哪条路**(DSM、SSH 别名、控制台),不抛异常。
175
+
176
+ > ⚠️ **深信服目前只有 `--status` 可用**:这版 SCP 不认现有重启端点(实测 404),命令会如实报错
177
+ > 并指向替代路径(Linux 走 SSH、Windows 去控制台)。端点考古与下一步见「待办」。
178
+
179
+ 目标解析由严到宽:精确 ID → 精确名 → 忽略大小写 → 唯一子串;**匹配到多台一律列出来让你挑**
180
+ (`srv07/srv08`、`泛微OA 应用/数据库` 这类同前缀名太多,猜错就是重启错生产机)。
181
+ 重启属低风险可逆,按安全模型**免二次确认**直接执行,并自动记一条操作日志(`--source` 声明调用方)。
182
+
183
+ ## 安全模型
184
+
185
+ | 操作类型 | 行为 |
186
+ |---|---|
187
+ | 只读(describe/list/get、df/状态查询等) | **自动执行**,不打扰 |
188
+ | 实例重启(`ops reboot`、各云 reboot API) | **自动执行**,低风险可逆;自动记审计日志 |
189
+ | 其它写操作(启停/销毁/改配置、远程改动、写文件) | **先弹确认**,y 才执行 |
190
+
191
+ 分类逻辑在 `src/noc_ops/aws_safety.py`,保守原则:**拿不准一律当写操作、要确认**。
192
+
193
+ > ⚠️ 关键实现点:写操作工具**不能**放进 `ClaudeAgentOptions.allowed_tools`——那会被 SDK 自动批准、绕过确认回调。只有纯只读内置工具(Read/Glob/Grep)放 allowed_tools,其余都走 `can_use_tool` 闸门。
194
+
195
+ ## 怎么加一项新能力(沉淀 runbook)
196
+
197
+ 1. 在交互模式里和 Agent 一起把某项运维做完。
198
+ 2. Agent 会主动问要不要沉淀;同意后它按 `_TEMPLATE.md` 在 `runbooks/` 生成剧本。
199
+ 3. 下次遇到同类需求,Agent 会先 Glob 到这个剧本、照着执行。
200
+
201
+ **加能力 ≈ 写一个 markdown,不用改代码。**
202
+
203
+ ## 开发 / 测试
204
+
205
+ 改本仓代码时的约定见 `CLAUDE.md`(给 LLM 客户端读的简版);下面是完整版。
206
+
207
+ ### 改完 src/ 必须重装全局 ops
208
+ 全局 `ops` 是 `uv tool` 装的 wheel **拷贝**,不跟随 `src/`。改完源码(尤其新增子命令)立刻:
209
+
210
+ ```bash
211
+ uv tool install --force --no-cache '<本仓绝对路径>[all]' # [all] 带上 agent+mcp 可选依赖,别把本机 agent 弄丢
212
+ ```
213
+
214
+ 漏这步的典型症状是「代码明明改好了、跑起来还是旧行为」,排查成本极高。
215
+
216
+ ### 测试(两层)
217
+
218
+ ```bash
219
+ uv run --extra dev pytest -m unit -q # Tier 1:离线、零 LLM、秒级,改完就跑
220
+ uv run --extra dev pytest -m eval -q # Tier 2:agent 行为评测,真调 LLM(要 ANTHROPIC_API_KEY,花钱)
221
+ uv run --extra dev pytest -q # 全部(没设 key 时 Tier 2 自动跳过)
222
+ ```
223
+
224
+ 日常只跑 `-m unit`。Tier 2 用 stub 挡住执行层(`agent._run_cli` / `agent._confirm`)+ 冻结的 fixtures 工作区,**绝不碰真云**;细节见 `tests/README.md`。
225
+
226
+ ### 新增 provider / 资源种类 / 看板 tab 的同步清单
227
+ 这几处必须一起改,漏一处就出现「看板有、agent 不知道」:
228
+
229
+ 1. `src/noc_ops/providers/<cloud>.py` + `sync.py` —— 扫出来、并进 `data.json`
230
+ 2. `src/noc_ops/dashboard/index.html` —— tab 与列
231
+ 3. `src/noc_ops/skill/SKILL.md.tmpl` —— agent 靠它才知道查什么、怎么查(公开 skill 仓 pholex/multicloud-ops 里 `skills/multicloud-ops/SKILL.md` 的云列表同步)
232
+ 4. `README.md` —— tab 列表与能力描述
233
+ 5. 改完跑 `ops setup` 重扇出 skill,再按上面重装全局 `ops`
234
+
235
+ ### 数据文件不入库
236
+ 仓根目录同时**就是**当前工作区,所以混着两类东西:`data.json` / `inventory.md` / `.state/` / `local-servers.toml` 都是 `ops sync` 等生成的产物,**不手改、不入库**(已在 `.gitignore`;含 IP/账号/命令,勿外泄)。要改内容,改生成它们的代码。
237
+ 真实的 `ops-config.toml` 与 `runbooks/` 同样是工作区数据、不入库;单测读的是匿名化夹具 `tests/fixtures/workspace/ops-config.toml`。
238
+
239
+ 秘密(token / PAT / 密码)走 macOS Keychain 或 Parameter Store,**不进仓库、也不进 `ops-config.toml`**。
240
+
241
+ ### 分发构建
242
+ 分发形态(2026-10-25 定):**skill 免费公开 + CLI 发 PyPI(纯 `py3-none-any`,macOS / Linux)+ 收费只圈 pro 场景**。
243
+
244
+ ```bash
245
+ uv build # dist/noc_ops-<版本>-py3-none-any.whl + sdist
246
+ uv publish # 推 PyPI(token 走环境变量 UV_PUBLISH_TOKEN,不进仓库)
247
+ ```
248
+
249
+ 发布前在干净环境过一遍 `INSTALL.md`(本地 Docker:`python:3.12-slim` 装 wheel → `ops setup` → `ops doctor` → `ops sync` → `ops noc`)。
250
+ `scripts/build-obfuscated.sh`(PyArmor 混淆、仅 arm64 Mac)保留但不再是默认分发路径。
251
+
252
+ ## 插件子命令(entry point)
253
+
254
+ 公司 / 团队专属的子命令不进公开 wheel,放在自己的私有包里,经 entry point 组 `noc_ops.commands` 挂回 `ops`:
255
+
256
+ ```toml
257
+ # 私有包的 pyproject.toml
258
+ [project]
259
+ dependencies = ["noc-ops"]
260
+ [project.entry-points."noc_ops.commands"]
261
+ litellm = "noc_ops_internal.litellm_cli:main" # 被调函数签名 main(argv) -> int | None
262
+ ```
263
+
264
+ 装法:`uv tool install 'noc-ops[all]' --with <私有包路径或名>`。`ops help` 末尾会列出已装的插件命令;内建命令名不可被插件覆盖;插件加载失败只报该命令、不影响 `ops` 其余功能。插件读自己的配置段用 `deploy_config.section("<段名>")`。
265
+
266
+ ## 待办 / 后续
267
+
268
+ - [ ] SSH 通道:配置 `~/.ssh/config`(跳板机 ProxyJump + key 文件),登录元数据进 inventory,私钥/密码不进明文。
269
+ - [ ] 把常用运维逐步沉淀成 runbooks。
270
+ - [ ] 提交前固定跑 `uv run --extra dev pytest -m unit -q`(当前 739 例 / ~2s);有条件再接进 pre-commit hook 或 CI 自动化,别靠人记。
271
+ - [ ] **深信服 HCI 的重启端点未探明**(2026-09-18 实测):provider 里写的 `POST /janus/20180725/servers/{id}/action` 本机 SCP 返回 404,从来没调通过;`ops reboot` 对 sangfor 只有 `--status` 可用(读没问题)。已探明:真口疑似批量的 `POST /janus/20180725/servers/action`,必传 `server_ids` + `server_action`(dict,`{}` 能过校验但 503),但其字段名 36 个候选全被拒、appliance 无 swagger/doc。**最省事的解法**:在 SCP 控制台点一次「重启」,devtools 抓那条 XHR 的 path+payload,照着改 `providers/sangfor.py` 的 `_reboot_server` 即可(考古记录在该文件头注)。在那之前:Linux VM 走 SSH 别名 `reboot`,Windows 去控制台点。
272
+
273
+ ## 许可
274
+
275
+ Apache License 2.0,见 `LICENSE` 与 `NOTICE`。看板自托管的第三方前端组件(AG Grid Community / Inter 字体)各随其原许可(MIT / OFL 1.1)。