# 帳票設計書 67-GoTemplate出力

## 概要

本ドキュメントは、GoテンプレートによるカスタムフォーマットでKubernetesリソース情報を出力する帳票の設計書である。`kubectl get <resource> -o go-template='{...}'` コマンド実行時に、Go標準の`text/template`構文で指定されたテンプレートに従ってリソース情報を標準出力に出力する。

### 本帳票の処理概要

**業務上の目的・背景**：JSONPath出力よりも高度なテンプレートロジック（条件分岐、ループ、パイプライン処理など）が必要な場面において、Go標準のtext/templateエンジンの全機能を活用してカスタム出力を実現する。Goに精通したエンジニアにとっては馴染みやすい構文であり、レポート生成や複雑なデータ加工に適している。

**帳票の利用シーン**：条件分岐を含む複雑な出力フォーマットが必要な場合、base64デコードされたSecret値を直接表示したい場合、Goテンプレートの制御構文（if/range/with等）を活用したい場合に利用される。

**主要な出力内容**：
1. Goテンプレート式で指定されたフィールド値をテキスト形式で出力
2. exists関数（フィールド存在チェック）とbase64decode関数（base64デコード）が追加関数として利用可能
3. missingkey制御（デフォルトではエラー、AllowMissingKeysでデフォルト値に変更可能）

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

**帳票の利用者**：DevOpsエンジニア、SRE、Goに精通した開発者。

## 帳票種別

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

## 利用画面

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

## 出力形式

### 基本仕様

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

## 帳票レイアウト

### レイアウト概要

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

```
# 例: kubectl get pods -o go-template='{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'
pod1
pod2
pod3

# 例: base64decode関数の使用
# kubectl get secret my-secret -o go-template='{{range $k,$v := .data}}{{$k}}: {{$v | base64decode}}{{"\n"}}{{end}}'
username: admin
password: secret123
```

### ヘッダー部

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

### 明細部

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

### フッター部

該当なし

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| 出力フォーマット指定 | `-o go-template='{...}'` または `-o go-template-file=<file>` | Yes |
| Goテンプレート式 | 出力フォーマットを定義するGoテンプレート | Yes |

### ソート順

APIサーバが返すデフォルト順序に従う。

### 改ページ条件

改ページなし

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

### 参照テーブル一覧

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

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| テンプレート評価 | `p.template.Execute(w, out)` (safeExecute経由) | N/A | text/templateエンジンを使用 |
| オブジェクト変換 | `json.Marshal(obj)` → `json.Unmarshal(data, &out)` で`map[string]interface{}`に変換 | N/A | - |
| base64デコード | `base64.StdEncoding.DecodeString(v)` | N/A | テンプレート内でパイプライン使用可能 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[kubectl get resource -o go-template 実行] --> B[コマンド引数・フラグ解析]
    B --> C[Goテンプレート解析]
    C --> D[NewGoTemplatePrinter生成]
    D --> E[APIサーバからリソース取得]
    E --> F[GoTemplatePrinter.PrintObj呼び出し]
    F --> G[内部オブジェクトチェック]
    G --> H[json.Marshal → json.Unmarshal]
    H --> I[safeExecute実行]
    I -->|成功| J[結果をWriterに出力]
    I -->|パニック| K[パニックをキャッチしエラー返却]
    I -->|エラー| L[デバッグ情報付きエラー出力]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 内部オブジェクトエラー | 内部表現のオブジェクトが渡された場合 | `InternalObjectPrinterErr` | 外部バージョンへの変換が必要 |
| テンプレート解析エラー | Goテンプレート構文が不正な場合 | template.Parseのエラーメッセージ | テンプレート構文の修正 |
| テンプレート実行エラー | テンプレート実行中にエラーが発生した場合 | `Error executing template: ...` + テンプレート・データのデバッグ情報 | テンプレートまたはデータの確認 |
| パニック捕捉 | テンプレートエンジンがパニックした場合 | `caught panic: ...` | テンプレートの修正 |
| base64デコードエラー | base64形式でないデータにbase64decodeを適用した場合 | `base64 decode failed: ...` | 入力データの確認 |

## パフォーマンス要件

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

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

GoテンプレートとJSONPath同様、任意のフィールドを抽出可能。base64decode関数によりSecretのエンコードデータを平文で表示できるため、出力先のアクセス制御に注意が必要である。safeExecuteによりテンプレートエンジンのパニックをキャッチし、安全に処理する。

## 備考

- GoTemplatePrinterは`cli-runtime/pkg/printers/template.go`で実装されている
- カスタム関数: `exists`（フィールド存在チェック、jsonpath.goから共有）、`base64decode`（base64デコード）
- `safeExecute`メソッドにより、テンプレートエンジンのパニックをrecoverで安全にキャッチ
- `AllowMissingKeys`メソッドでmissingkeyオプション（"default" or "error"）を制御可能
- k8s.io/apimachinery/pkg/util/jsonパッケージ（標準encoding/jsonの拡張）を使用

---

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

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

### 推奨読解順序

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

GoTemplatePrinterの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | template.go | `staging/src/k8s.io/cli-runtime/pkg/printers/template.go` | 32-35行目: GoTemplatePrinter構造体。rawTemplate(文字列)とtemplate(*template.Template)を持つ |

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

NewGoTemplatePrinter関数でのテンプレート解析とカスタム関数登録を理解する。

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

**主要処理フロー**:
1. **38-43行目**: `template.New("output").Funcs(...).Parse(string(tmpl))`でテンプレート生成。FuncMapに`exists`と`base64decode`を登録
2. **47-50行目**: rawTemplateとtemplateを保持するGoTemplatePrinterを返却

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

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

**主要処理フロー**:
- **64行目**: InternalObjectPreventerによる内部オブジェクトチェック
- **70行目**: `json.Marshal(obj)`でオブジェクトをJSON化
- **75-76行目**: `json.Unmarshal`でmap[string]interface{}に変換
- **79行目**: `p.safeExecute(w, out)`でテンプレート実行
- **83-87行目**: エラー時にデバッグ情報出力

#### Step 4: safeExecuteとbase64decodeを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | template.go | `staging/src/k8s.io/cli-runtime/pkg/printers/template.go` | 94-111行目: safeExecute関数。defer/recoverでパニックをキャッチ |
| 4-2 | template.go | `staging/src/k8s.io/cli-runtime/pkg/printers/template.go` | 113-119行目: base64decode関数 |

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

```
kubectl get <resource> -o go-template='{...}'
    |
    +-- PrintFlags.ToPrinter() (出力形式判定)
    |       |
    |       +-- NewGoTemplatePrinter(tmpl) [template.go:37]
    |               |
    |               +-- template.New("output").Funcs(exists, base64decode).Parse(tmpl)
    |
    +-- GoTemplatePrinter.PrintObj() [template.go:63]
            |
            +-- InternalObjectPreventer.IsForbidden()
            |
            +-- json.Marshal → json.Unmarshal (map化)
            |
            +-- safeExecute() [template.go:94]
                    |
                    +-- template.Execute(w, obj)
                    |
                    +-- defer recover() (パニックキャッチ)
```

### データフロー図

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

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

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| template.go | `staging/src/k8s.io/cli-runtime/pkg/printers/template.go` | ソース | GoTemplatePrinter実装 |
| jsonpath.go | `staging/src/k8s.io/cli-runtime/pkg/printers/jsonpath.go` | ソース | exists関数の定義元（共有） |
| interface.go | `staging/src/k8s.io/cli-runtime/pkg/printers/interface.go` | ソース | ResourcePrinterインターフェース定義 |
| template_test.go | `staging/src/k8s.io/cli-runtime/pkg/printers/template_test.go` | テスト | GoTemplatePrinterのテストケース |
