Add a `doctor` command for read-only environment and connectivity diagnostics
- 主要言語
- C#
- スター
- 3
- フォーク
- 7
- 平均マージ
- 1日 12時間
- マージ済み PR(30日)
- 14
説明
## Problem
Just an idea - cosmos/azure is very complex and problems tend to jump out of the box from nowehere. Would maybe be helpful to let the shell check problems for you before they occur.
After GA, the most common support traffic for a CLI is usually not feature requests — it is "it does not connect", "I get 403", or "it hangs". Diagnosing those today requires a round trip to collect shell version, install method, platform, auth mode, connection mode, endpoint, and RBAC state.
There is no single command that collects this and renders a verdict. `info` reports resource configuration and usage, and `connect` reports the current connection, but neither answers *what is broken and what to do about it*.
## Proposed solution
Add a read-only `doctor` command that runs a fixed set of checks and reports `PASS` / `WARN` / `FAIL` / `SKIP` with actionable remediation text.
```text
doctor
doctor --database MyDb --container Items
doctor --format json
```
Example output:
```text
PASS Shell version 1.0.213-preview (dotnet tool)
PASS Authentication Azure CLI credential acquired
PASS Account endpoint Reachable in 84 ms (Direct)
WARN Control plane No ARM context (account-key auth)
mkdb/mkcon/rmdb/rmcon/indexpolicy may fail under strict data-plane RBAC.
Reconnect with Entra ID, or pass --subscription and --resource-group.
FAIL Container access 403 Forbidden
Required data-plane role: Cosmos DB Built-in Data Reader
```
## Scope: three tiers
ARM is **not** required, and must stay optional.
| Tier | Requires | Checks |
| --- | --- | --- |
| 0 | nothing | shell version, OS/arch, install method, .NET runtime, relevant env vars, DNS, proxy, TLS, clock skew |
| 1 | data plane | credential acquisition, endpoint reachability, connection mode, database/container existence, read + query permission |
| 2 | ARM (opt-in) | account resource resolution, control-plane reachability, role assignments |
Tier 2 runs **only** when an ARM context already exists on the state, or when the user passes `--arm` explicitly. A missing ARM context is reported as `SKIP`, never `FAIL`.
### Why ARM must stay optional
- `CosmosArmResourceProvider.TryCreateContextAsync` returns `null` immediately when `credential == null`, so account-key and connection-string auth have no ARM context at all.
- The emulator has no ARM.
- `CosmosArmResourceProvider.DiscoverContextAsync` enumerates every subscription and every Cosmos account until the endpoint matches. That is far too slow to sit on a diagnostic command's default path.
- CI and workload-identity principals frequently have no ARM permission by design.
## Notable checks
1. **ARM-context gap (highest value).** The comment above `CosmosArmResourceProvider.TryCreateContextAsync` already documents this: key auth means no ARM context, so control-plane commands (`mkdb`, `mkcon`, `rmdb`, `rmcon`, `indexpolicy`) fall back to the data plane and then fail on accounts with strict data-plane RBAC. `doctor` should name this explicitly instead of leaving users to discover it through a failed command.
2. **RBAC parsing reuse.** `InfoCommand.PrincipalIdRegex` already parses `does not have required RBAC permissions to perform action`. Extract and reuse it rather than writing a second parser.
3. **Direct-mode port probe.** Direct mode needs outbound TCP 10250-10256. On corporate networks this presents as a hang rather than an error; the check should recommend `--connect-mode gateway`.
4. **Clock skew.** Drift beyond roughly 5 minutes breaks token validation with unhelpful errors.
5. **Emulator certificate.** Certificate validation is bypassed only for emulator endpoints, so a self-signed certificate on a non-emulator endpoint should be flagged rather than silently failing.
## Non-goals for v1
- No `--fix` and no mutating behavior. `doctor` stays read-only so it is safe to run and safe to paste into an issue.
- No duplication of `info` or `connect` output beyond what a verdict requires.
## Acceptance criteria
- [ ] `doctor` runs with no connection and still produces Tier 0 results
- [ ] Tier 1 checks run against the current or specified database/container
- [ ] Tier 2 is skipped cleanly when no ARM context is present; `--arm` opts in
- [ ] `--database` / `--container` target explicitly, consistent with other commands
- [ ] Text output plus stable `--format json` output
- [ ] Non-zero exit code when a required check fails (aligns with the non-interactive output contract in #155)
- [ ] Output never contains keys, tokens, connection strings, or document data
- [ ] Golden-file redaction test: run against a connection carrying a known key and token, assert neither appears in text or JSON output
- [ ] Unit tests for severity resolution and remediation mapping
- [ ] Exposed over MCP as a read-only tool so agents can self-diagnose connectivity
- [ ] Help strings added to `lang/en.ftl`
- [ ] Documented in `docs/commands.md` plus a troubleshooting section
コントリビューションガイド
調査の方向性
まず CLI コマンドの登録と既存の InfoCommand.PrincipalIdRegex を追跡し、次に CosmosArmResourceProvider.TryCreateContextAsync と DiscoverContextAsync を読んで ARM の動作を理解します。既存のコマンドターゲティング、出力、MCP、ローカライズ、ドキュメントのエントリポイントを確認します。これには lang/en.ftl と docs/commands.md が含まれます。読み取り専用の段階的なチェック、安定したテキストおよび JSON 出力、redaction と severity のテスト、正しい終了コード、ARM のクリーンなスキップがあれば完了です。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- azure, csharp
- 領域
- cli, cloud, documentation, testing
- issue の種類
- 機能追加
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 活発
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 35/100