# 帳票設計書 66-JSONPath出力

## 概要

本ドキュメントは、JSONPathテンプレートによるカスタム形式でKubernetesリソース情報を出力する帳票の設計書である。`kubectl get <resource> -o jsonpath='{...}'` コマンド実行時に、JSONPath式で指定されたフィールドのみを抽出して標準出力に出力する。

### 本帳票の処理概要

**業務上の目的・背景**：リソースの全フィールドではなく、特定のフィールドのみを効率的に抽出する必要がある場面が多い。JSONPath出力はシェルスクリプトやパイプライン処理において、jqなどの外部ツールを使用せずにkubectl単体でフィールド抽出を実現するための機能である。テーブル出力では得られない任意のフィールドを自由に組み合わせて出力できる。

**帳票の利用シーン**：シェルスクリプトから特定のフィールド値を取得する場合（例: Pod名一覧、ノードのIPアドレス一覧）、条件付きフィルタリングやイテレーションを行う場合、CI/CDパイプラインで特定の値を環境変数に設定する場合に利用される。

**主要な出力内容**：
1. JSONPath式で指定されたフィールド値のみをテキスト形式で出力
2. 配列のイテレーション、条件付き抽出（フィルタ式）に対応
3. exists関数によるフィールド存在チェックが利用可能

**帳票の出力タイミング**：`kubectl get <resource> -o jsonpath='{...}'` または `-o jsonpath-file=<file>` コマンド実行時に出力される。

**帳票の利用者**：DevOpsエンジニア、SRE、シェルスクリプト作成者、CI/CDパイプライン。

## 帳票種別

データ出力（カスタムフォーマット）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | CLI（ターミナル） | - | `kubectl get <resource> -o jsonpath='{...}'` コマンド実行 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト（カスタムフォーマット） |
| 用紙サイズ | N/A（ターミナル出力） |
| 向き | N/A |
| ファイル名 | N/A（標準出力） |
| 出力方法 | 標準出力（stdout） |
| 文字コード | UTF-8 |

## 帳票レイアウト

### レイアウト概要

JSONPath式のテンプレートに従って出力される。出力形式はテンプレートの内容によって自由に定義可能。

```
# 例: kubectl get pods -o jsonpath='{.items[*].metadata.name}'
pod1 pod2 pod3

# 例: kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.addresses[0].address}{"\n"}{end}'
node1   192.168.1.1
node2   192.168.1.2
```

### ヘッダー部

該当なし（テンプレートにより自由に定義）

### 明細部

テンプレート式により動的に決定される。

### フッター部

該当なし

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| 出力フォーマット指定 | `-o jsonpath='{...}'` または `-o jsonpath-file=<file>` | Yes |
| JSONPath式 | 抽出するフィールドを指定するJSONPath式 | Yes |

### ソート順

APIサーバが返すデフォルト順序に従う。JSONPath式内のrangeでイテレーション順は入力データの順序に依存。

### 改ページ条件

改ページなし

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| etcd: /registry/<resource>/ | 各リソースの永続化ストア | APIサーバ経由でRESTアクセス |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| JSONPath評価 | `j.JSONPath.Execute(w, queryObj)` | N/A | k8s.io/client-go/util/jsonpath パッケージを使用 |
| クエリオブジェクト変換 | Unstructuredの場合はUnstructuredContent()、それ以外はjson.Marshal→json.Unmarshalで`map[string]interface{}`に変換 | N/A | - |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[kubectl get resource -o jsonpath 実行] --> B[コマンド引数・フラグ解析]
    B --> C[JSONPathテンプレート解析]
    C --> D[NewJSONPathPrinter生成]
    D --> E[APIサーバからリソース取得]
    E --> F[JSONPathPrinter.PrintObj呼び出し]
    F --> G[内部オブジェクトチェック]
    G --> H{Unstructured?}
    H -->|Yes| I[UnstructuredContent取得]
    H -->|No| J[json.Marshal → json.Unmarshal]
    I --> K[JSONPath.Execute実行]
    J --> K
    K -->|成功| L[結果をWriterに出力]
    K -->|失敗| M[デバッグ情報付きエラー出力]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 内部オブジェクトエラー | 内部表現のオブジェクトが渡された場合 | `InternalObjectPrinterErr` | 外部バージョンへの変換が必要 |
| テンプレート解析エラー | JSONPath式の構文が不正な場合 | NewJSONPathPrinter時のパースエラー | JSONPath式の構文を修正 |
| テンプレート実行エラー | 指定フィールドが存在しない等 | `error executing jsonpath "...": ...` + デバッグ情報 | JSONPath式やリソース構造を確認 |
| JSONシリアライズエラー | オブジェクトのJSON変換に失敗した場合 | json.Marshalのエラーメッセージ | オブジェクト構造の確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 1件〜数千件（リソース種別に依存） |
| 目標出力時間 | JSONPath式の複雑さとデータサイズに依存 |
| 同時出力数上限 | N/A（CLI単発実行） |

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

JSONPath式により任意のフィールドを抽出可能であるため、Secretのdataフィールド等の機密情報も取得できる。InternalObjectPreventerにより内部オブジェクトの外部漏洩を防止している。

## 備考

- JSONPathPrinterは`cli-runtime/pkg/printers/jsonpath.go`で実装されている
- カスタム関数`exists`が利用可能（フィールドの存在チェック）
- `indirect`ヘルパー関数でポインタやインターフェースを透過的に処理
- エラー時にはテンプレート内容とオブジェクト構造のデバッグ情報が出力される
- JSONPath式の構文はKubernetes独自の拡張を含む（k8s.io/client-go/util/jsonpath）

---

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

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

### 推奨読解順序

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

JSONPathPrinterの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | jsonpath.go | `staging/src/k8s.io/cli-runtime/pkg/printers/jsonpath.go` | 100-104行目: JSONPathPrinter構造体。rawTemplate(文字列)と*jsonpath.JSONPath(埋め込み)を持つ |

**読解のコツ**: JSONPathPrinterはjsonpath.JSONPathを埋め込んでいるため、jsonpath.JSONPathのメソッドが直接利用可能。

#### Step 2: ファクトリ関数を理解する

NewJSONPathPrinter関数でのテンプレート解析を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | jsonpath.go | `staging/src/k8s.io/cli-runtime/pkg/printers/jsonpath.go` | 106-115行目: NewJSONPathPrinter関数 |

**主要処理フロー**:
1. **107行目**: `jsonpath.New("out")`で新規JSONPathインスタンス生成
2. **108行目**: `j.Parse(tmpl)`でテンプレート解析
3. **111-114行目**: rawTemplateとJSONPathを保持するJSONPathPrinterを返却

#### Step 3: PrintObj処理を理解する

PrintObjメソッドでのオブジェクト変換とテンプレート実行を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | jsonpath.go | `staging/src/k8s.io/cli-runtime/pkg/printers/jsonpath.go` | 118-148行目: PrintObj関数 |

**主要処理フロー**:
- **122行目**: InternalObjectPreventerによる内部オブジェクトチェック
- **126-138行目**: queryObjの構築。Unstructuredの場合はUnstructuredContent()、それ以外はjson.Marshal/Unmarshalでmap変換
- **140-146行目**: `j.JSONPath.Execute(w, queryObj)`でテンプレート実行。失敗時はデバッグ情報付きエラー

#### Step 4: ヘルパー関数を理解する

exists関数とindirect関数の動作を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | jsonpath.go | `staging/src/k8s.io/cli-runtime/pkg/printers/jsonpath.go` | 39-82行目: exists関数（配列/マップのインデックスアクセスの存在チェック） |
| 4-2 | jsonpath.go | `staging/src/k8s.io/cli-runtime/pkg/printers/jsonpath.go` | 88-98行目: indirect関数（ポインタ/インターフェースの間接参照） |

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

```
kubectl get <resource> -o jsonpath='{...}'
    |
    +-- PrintFlags.ToPrinter() (出力形式判定)
    |       |
    |       +-- NewJSONPathPrinter(tmpl) [jsonpath.go:106]
    |               |
    |               +-- jsonpath.New("out") + Parse(tmpl)
    |
    +-- JSONPathPrinter.PrintObj() [jsonpath.go:118]
            |
            +-- InternalObjectPreventer.IsForbidden()
            |
            +-- queryObj構築 (Unstructured or json.Marshal/Unmarshal)
            |
            +-- JSONPath.Execute(w, queryObj)
```

### データフロー図

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

runtime.Object           -->  JSONPathPrinter.PrintObj         -->  標準出力
(APIサーバから取得)              |                                    (テンプレート評価結果)
                               +-- json.Marshal/Unmarshal
JSONPath テンプレート     -->  |   (map[string]interface{}化)
(-o jsonpath='{...}')          +-- JSONPath.Execute
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| jsonpath.go | `staging/src/k8s.io/cli-runtime/pkg/printers/jsonpath.go` | ソース | JSONPathPrinter実装 |
| interface.go | `staging/src/k8s.io/cli-runtime/pkg/printers/interface.go` | ソース | ResourcePrinterインターフェース定義 |
| jsonpath_test.go | `staging/src/k8s.io/cli-runtime/pkg/printers/jsonpath_test.go` | テスト | JSONPathPrinterのテストケース |
| jsonpath/ | `staging/src/k8s.io/client-go/util/jsonpath/` | ソース | JSONPathエンジン本体 |
