# 機能設計書 110-explain

## 概要

本ドキュメントは、`kubectl explain` コマンドによるリソースフィールド説明表示機能の設計を記述する。リソースの各フィールドの型情報と説明をOpenAPIスキーマから取得して表示する。

### 本機能の処理概要

**業務上の目的・背景**：Kubernetesのリソースマニフェストを記述する際、各フィールドの意味や型、必須/任意の区別を把握する必要がある。`kubectl explain` はクラスターのOpenAPIスキーマからフィールド情報を取得し、ドキュメントとして表示することで、マニフェスト作成の効率化を支援する。

**機能の利用シーン**：マニフェストファイル作成時のフィールド確認、CRDフィールドの確認、APIバージョン間のフィールド差異確認、ネストされたフィールド構造の探索に利用される。

**主要な処理内容**：
1. リソースタイプの解析とGVR解決
2. OpenAPI V3スキーマの取得（V3優先、V2フォールバック）
3. フィールドパスの解析（例: pods.spec.containers）
4. スキーマ情報のフォーマットと表示

**関連システム・外部連携**：OpenAPI V3 / V2 API

**権限による制御**：OpenAPIスキーマへのアクセス権限が必要（通常は全ユーザーに付与）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 34 | kubectl explain | 主機能 | リソースフィールドの説明を表示 |

## 機能種別

情報表示・スキーマ探索

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| TYPE | string | Yes | リソースタイプ（例: pods, pods.spec.containers） | 1つだけ指定可 |
| --api-version | string | No | 特定のAPIバージョンを指定 | group/version 形式 |
| -R / --recursive | bool | No | フィールドを再帰的に表示 | デフォルト: false |
| -o / --output | string | No | 出力形式 | plaintext / plaintext-openapiv2 |

### 入力データソース

- コマンドライン引数（リソースタイプ + フィールドパス）
- OpenAPI V3 / V2 API（スキーマ情報）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| KIND | string | リソースのKind |
| VERSION | string | APIバージョン |
| DESCRIPTION | text | リソースまたはフィールドの説明 |
| FIELDS | tree | フィールド一覧（名前、型、説明） |

### 出力先

標準出力（stdout）にテキスト形式で表示

## 処理フロー

### 処理シーケンス

```
1. 引数パースとバリデーション
   └─ TYPE引数が1つのみ必須
2. ExplainFlags -> ExplainOptions変換
   ├─ RESTMapper初期化
   └─ OpenAPI V3 Client初期化
3. リソースタイプの解析
   ├─ [--api-version未指定] SplitAndParseResourceRequestWithMatchingPrefix
   └─ [--api-version指定] SplitAndParseResourceRequest
4. GVR解決
   └─ "." 区切りでリソースタイプとフィールドパスを分離
5. スキーマ取得と表示
   ├─ [plaintext] OpenAPI V3 -> PrintModelDescription
   ├─ [plaintext-openapiv2] OpenAPI V2 -> PrintModelDescription
   └─ [V3未対応] フォールバックで OpenAPI V2 使用
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[引数パース TYPE]
    B --> C{引数バリデーション}
    C -->|0個| D[エラー: TYPE必須]
    C -->|2個以上| E[エラー: 1つのみ]
    C -->|1個| F[リソースタイプ + フィールドパス解析]
    F --> G{--output 形式}
    G -->|plaintext-openapiv2| H[OpenAPI V2 レンダリング]
    G -->|plaintext| I{V3対応?}
    I -->|Yes| J[OpenAPI V3 レンダリング]
    I -->|No| H
    G -->|その他| J
    H --> K[PrintModelDescription V2]
    J --> L[PrintModelDescription V3]
    K --> M[終了]
    L --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-1001 | V3優先 | デフォルトはOpenAPI V3を使用し、V3未対応クラスターではV2にフォールバック | plaintext出力時 |
| BR-1002 | フィールドパス解析 | "." 区切りでリソースタイプからフィールドパスを分離（例: pods.spec.containers） | 常に適用 |
| BR-1003 | --api-version指定時 | 指定バージョンのスキーマを使用（Group/Versionの上書き） | --api-version指定時 |
| BR-1004 | 再帰表示 | --recursive で全フィールドを再帰的に展開（現在は1レベルのみ対応） | --recursive指定時 |
| BR-1005 | MatchingPrefix | --api-version未指定時、リソース名のプレフィックスマッチで解決を試行 | --api-version未指定時 |
| BR-1006 | 出力形式 | plaintext（V3ベース）、plaintext-openapiv2（V2ベース） | -o フラグ |

### 計算ロジック

フィールドパス解析: `pods.spec.containers` を `pods` (リソースタイプ) と `["spec", "containers"]` (フィールドパス) に分離する。RESTMapperで完全修飾GVRに解決後、OpenAPIスキーマを走査する。

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| スキーマ取得 | OpenAPI V3/V2 API | SELECT | リソーススキーマの読み取り |

### テーブル別操作詳細

読み取り専用。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 引数なし | TYPE未指定 | "You must specify the type of resource to explain" |
| - | 引数過多 | 2つ以上の引数 | "We accept only this format: explain RESOURCE" |
| - | リソース未発見 | 指定リソースのスキーマがない | "couldn't find resource for X" |
| - | V3未対応 | OpenAPI V3 APIが利用できない | V2にフォールバック |

### リトライ仕様

特にリトライ処理は実装されていない。

## トランザクション仕様

読み取り専用の参照処理であり、トランザクション管理は不要。

## パフォーマンス要件

OpenAPIスキーマの取得は初回にキャッシュされる場合がある。大規模なCRDがある環境ではスキーマ取得に時間がかかる可能性がある。

## セキュリティ考慮事項

- OpenAPIスキーマはリソース構造の情報であり、データ自体の機密性はない
- ただし、CRDのスキーマにはアプリケーション固有の設計情報が含まれる場合がある

## 備考

- `kubectl explain pods --recursive` の再帰レベルは現在1レベルのみ対応（注記あり）
- `--api-version` でバージョンを指定すると、そのバージョン固有のフィールドが表示される
- CRDのフィールド説明は、CRD定義にOpenAPI Validation Schemaが含まれている場合のみ表示される

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | explain.go | `staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go` | ExplainFlags構造体（72-78行目）：CLIフラグ |
| 1-2 | explain.go | `staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go` | ExplainOptions構造体（150-166行目）：ランタイムオプション |

**読解のコツ**: ExplainFlagsがCLI入力を、ExplainOptionsがランタイム処理を担当するパターン。OpenAPIV3ClientとopenAPIGetterの2つのスキーマ取得手段を持つ。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | explain.go | `staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go` | NewCmdExplain関数（128-148行目）：コマンド定義 |
| 2-2 | explain.go | `staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go` | **64-67行目**: 出力形式定数（plaintext / plaintext-openapiv2） |

#### Step 3: オプション変換を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | explain.go | `staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go` | ToOptions関数（96-125行目）：Factory -> Options変換 |
| 3-2 | explain.go | `staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go` | **103行目**: OpenAPI V3 Client初期化 |

#### Step 4: メイン処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | explain.go | `staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go` | Run関数（180-230行目）：メイン処理 |
| 4-2 | explain.go | `staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go` | **184-197行目**: リソースタイプ解析とGVR解決 |
| 4-3 | explain.go | `staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go` | **200-229行目**: V3/V2 レンダリング分岐 |

**主要処理フロー**:
- **201行目**: plaintext-openapiv2 -> renderOpenAPIV2()
- **203-208行目**: plaintext -> V3試行、失敗時V2フォールバック
- **221-228行目**: V3 PrintModelDescription呼び出し

#### Step 5: V2フォールバック処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | explain.go | `staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go` | renderOpenAPIV2関数（232-264行目）：V2スキーマでのレンダリング |
| 5-2 | explain.go | `staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go` | **238-244行目**: KindFor()によるGVK解決 |
| 5-3 | explain.go | `staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go` | **254行目**: OpenAPISchema()でV2スキーマ取得 |
| 5-4 | explain.go | `staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go` | **258-261行目**: LookupResourceでスキーマ検索 |

### プログラム呼び出し階層図

```
NewCmdExplain
    │
    ├─ ExplainFlags.ToOptions()
    │      ├─ Factory.ToRESTMapper()
    │      └─ Factory.OpenAPIV3Client()
    │
    ├─ ExplainOptions.Validate()
    │
    └─ ExplainOptions.Run()
           ├─ SplitAndParseResourceRequest[WithMatchingPrefix]()
           │      └─ RESTMapper.ResourceFor()
           │
           ├─ [plaintext-openapiv2] renderOpenAPIV2()
           │      ├─ Mapper.KindFor()
           │      ├─ openAPIGetter.OpenAPISchema()
           │      ├─ resources.LookupResource()
           │      └─ explain.PrintModelDescription()
           │
           └─ [plaintext / default] openapiv3explain.PrintModelDescription()
                  └─ OpenAPIV3Client.Paths()
```

### データフロー図

```
[入力]                    [処理]                            [出力]

TYPE引数 ──▶ SplitAndParseResourceRequest ──▶ GVR + FieldsPath
                                                    │
OpenAPI V3/V2 API ◀── Client ◀─────────────────────┘
       │                                            │
       ▼                                            ▼
   スキーマ情報 ──▶ PrintModelDescription ──▶ テキスト表示 ──▶ stdout
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| explain.go | `staging/src/k8s.io/kubectl/pkg/cmd/explain/explain.go` | ソース | コマンド定義・メインロジック |
| explain/ | `staging/src/k8s.io/kubectl/pkg/explain/` | パッケージ | V2スキーマ解析・表示ロジック |
| explain/v2/ | `staging/src/k8s.io/kubectl/pkg/explain/v2/` | パッケージ | V3スキーマ解析・表示ロジック |
| explain_test.go | `staging/src/k8s.io/kubectl/pkg/cmd/explain/explain_test.go` | テスト | ユニットテスト |
