# 帳票設計書 65-YAML出力

## 概要

本ドキュメントは、Kubernetesリソース情報をYAML形式で出力する帳票の設計書である。`kubectl get <resource> -o yaml` コマンド実行時に、リソースの完全な構造化データをYAMLフォーマットで標準出力に出力する。

### 本帳票の処理概要

**業務上の目的・背景**：YAMLはKubernetesマニフェストの標準記述形式であり、リソース定義の作成・編集・バックアップにおいて最も頻繁に使用されるフォーマットである。JSON出力と同様にリソースの全フィールドが含まれるが、YAML形式はJSONよりも人間にとって可読性が高く、マニフェストファイルとして直接再利用しやすい特徴がある。

**帳票の利用シーン**：既存リソースのマニフェストをエクスポートする場合、リソース定義のテンプレートを作成する場合、リソースの詳細情報を確認しつつ可読性を重視する場合、GitOpsワークフローでのマニフェスト管理に利用される。

**主要な出力内容**：
1. リソースの全フィールド（apiVersion, kind, metadata, spec, status等）をYAML形式で出力
2. 複数オブジェクト出力時は`---`セパレータで区切る
3. sigs.k8s.io/yamlライブラリによるシリアライズ

**帳票の出力タイミング**：`kubectl get <resource> -o yaml` コマンド実行時に出力される。

**帳票の利用者**：DevOpsエンジニア、SRE、アプリケーション開発者、クラスタ管理者。

## 帳票種別

データ出力（構造化データ）

## 利用画面

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

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | YAML |
| 用紙サイズ | N/A（ターミナル出力） |
| 向き | N/A |
| ファイル名 | N/A（標準出力。リダイレクトで任意のファイルに保存可能） |
| 出力方法 | 標準出力（stdout） |
| 文字コード | UTF-8 |

## 帳票レイアウト

### レイアウト概要

YAML形式でリソース情報が出力される。複数オブジェクトの場合は`---`で区切られる。

```
apiVersion: v1
kind: Pod
metadata:
  name: example-pod
  namespace: default
spec:
  containers:
  - name: nginx
    image: nginx:latest
status:
  phase: Running
```

### ヘッダー部

該当なし（YAML構造の一部としてapiVersion, kind等が含まれる）

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | 全フィールド | リソースの完全な構造化データ | runtime.Object | YAML形式 |

### フッター部

該当なし

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| 出力フォーマット指定 | `-o yaml` オプション | Yes |
| リソース種別 | 任意のKubernetesリソース | Yes |

### ソート順

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

### 改ページ条件

改ページなし。複数オブジェクト出力時は`---`セパレータで区切り。

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

### 参照テーブル一覧

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

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| YAML出力 | `yaml.Marshal(obj)` | N/A | sigs.k8s.io/yamlライブラリ使用 |
| セパレータ | printCount > 1 の場合に`---\n`を先頭に付加 | N/A | atomic.AddInt64でスレッドセーフにカウント |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[kubectl get resource -o yaml 実行] --> B[コマンド引数・フラグ解析]
    B --> C[出力フォーマット判定: YAML]
    C --> D[YAMLPrinter生成]
    D --> E[APIサーバからリソース取得]
    E --> F[YAMLPrinter.PrintObj呼び出し]
    F --> G{printCount > 1?}
    G -->|Yes| H["'---' セパレータ出力"]
    G -->|No| I[セパレータなし]
    H --> J{オブジェクト種別判定}
    I --> J
    J -->|WatchEvent| K[yaml.Marshal]
    J -->|runtime.Unknown| L[yaml.JSONToYAML で変換]
    J -->|通常オブジェクト| M[GVK空チェック]
    M -->|空| N[エラー]
    M -->|あり| O[yaml.Marshal で出力]
    K --> P[Writer に書き込み]
    L --> P
    O --> P
    P --> Q[標準出力に表示]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 内部オブジェクトエラー | 内部表現のオブジェクトが渡された場合 | `InternalObjectPrinterErr` | 外部バージョンへの変換が必要 |
| GVK未設定エラー | apiVersionまたはkindが空の場合 | `missing apiVersion or kind; try GetObjectKind().SetGroupVersionKind() if you know the type` | SetGroupVersionKindを呼び出す |
| YAMLシリアライズエラー | オブジェクトがYAML化できない場合 | yaml.Marshalのエラーメッセージ | オブジェクト構造の確認 |

## パフォーマンス要件

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

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

JSON出力と同様、YAML出力にはリソースの全フィールドが含まれるため、Secretリソースのdataフィールドなども出力される。InternalObjectPreventerにより内部オブジェクトの外部漏洩を防止している。

## 備考

- YAMLPrinterは`cli-runtime/pkg/printers/yaml.go`で実装されている
- printCountフィールドはint64型で、atomic.AddInt64を使用してスレッドセーフにインクリメントされる
- 2回目以降のPrintObj呼び出し時に`---`セパレータが付加される（Watch出力時に複数オブジェクトが順次出力される場合に使用）
- runtime.Unknown型の場合は`yaml.JSONToYAML`で生JSONデータをYAMLに変換する

---

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

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

### 推奨読解順序

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

YAMLPrinterの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | interface.go | `staging/src/k8s.io/cli-runtime/pkg/printers/interface.go` | 34-38行目: ResourcePrinterインターフェース |
| 1-2 | yaml.go | `staging/src/k8s.io/cli-runtime/pkg/printers/yaml.go` | 36-38行目: YAMLPrinter構造体。printCountフィールド（int64）を持つ |

**読解のコツ**: JSONPrinterと異なり、YAMLPrinterはprintCountを持つステートフルな構造体である。これは複数オブジェクト出力時の`---`セパレータ管理に使用される。

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

PrintObjメソッドの処理を理解する。

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

**主要処理フロー**:
1. **45行目**: `InternalObjectPreventer.IsForbidden`で内部オブジェクトチェック
2. **49-54行目**: `atomic.AddInt64(&p.printCount, 1)`でカウントインクリメント。count > 1なら`---\n`出力
3. **56-66行目**: `*metav1.WatchEvent`の場合: `yaml.Marshal`
4. **67-73行目**: `*runtime.Unknown`の場合: `yaml.JSONToYAML`で生JSONをYAMLに変換
5. **76-78行目**: GVKが空の場合はエラー
6. **80-85行目**: 通常オブジェクト: `yaml.Marshal`でYAML化し`fmt.Fprint`で出力

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

```
kubectl get <resource> -o yaml
    |
    +-- PrintFlags.ToPrinter() (出力形式判定)
    |       |
    |       +-- YAMLPrinter 生成
    |
    +-- YAMLPrinter.PrintObj() [yaml.go:41]
            |
            +-- InternalObjectPreventer.IsForbidden()
            |
            +-- atomic.AddInt64(&printCount) (セパレータ判定)
            |
            +-- switch obj.(type)
                    |
                    +-- *metav1.WatchEvent: yaml.Marshal()
                    |
                    +-- *runtime.Unknown: yaml.JSONToYAML()
                    |
                    +-- default: yaml.Marshal()
```

### データフロー図

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

runtime.Object     -->  YAMLPrinter.PrintObj            -->  標準出力
(APIサーバから取得)        |                                    (YAML形式テキスト)
                         +-- 内部オブジェクトチェック
                         +-- セパレータ判定(---)
                         +-- 型別分岐処理
                         +-- yaml.Marshal / yaml.JSONToYAML
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| yaml.go | `staging/src/k8s.io/cli-runtime/pkg/printers/yaml.go` | ソース | YAMLPrinter実装 |
| interface.go | `staging/src/k8s.io/cli-runtime/pkg/printers/interface.go` | ソース | ResourcePrinterインターフェース定義 |
| yaml_test.go | `staging/src/k8s.io/cli-runtime/pkg/printers/yaml_test.go` | テスト | YAMLPrinterのテストケース |
| kyaml.go | `staging/src/k8s.io/cli-runtime/pkg/printers/kyaml.go` | ソース | KubeYAMLPrinter（kyaml版実装） |
