# 画面設計書 31-kubectl patch

## 概要

本ドキュメントは、Kubernetes CLIツール `kubectl` の `patch` コマンドに関する画面設計書である。`kubectl patch` は、既存のKubernetesリソースのフィールドを部分的に更新するためのコマンドであり、Strategic Merge Patch、JSON Merge Patch、JSON Patchの3つのパッチ方式をサポートする。

### 本画面の処理概要

**業務上の目的・背景**：Kubernetesクラスター上のリソースを更新する際、リソース全体を再定義する必要なく、特定のフィールドのみを変更したいケースが頻繁に発生する。例えば、Deploymentのレプリカ数の変更、Podのコンテナイメージの更新、Nodeのスケジュール不可設定など、部分的な変更を効率的に行うために `kubectl patch` コマンドが提供されている。これにより、運用時の迅速なリソース変更やCI/CDパイプラインにおける自動化が実現される。

**画面へのアクセス方法**：ターミナルから `kubectl patch` コマンドを実行する。リソースの指定はTYPE NAME形式または `-f FILENAME` によるファイル指定で行う。パッチ内容は `-p` フラグでインライン指定するか、`--patch-file` でファイルから読み込む。

**主要な操作・処理内容**：
1. パッチタイプの選択（strategic / merge / json）とパッチ内容の指定
2. 対象リソースの特定（リソースタイプ+名前、またはファイル指定）
3. パッチのJSON変換とバリデーション
4. API Serverへのパッチリクエスト送信（サーバーサイド処理）
5. ローカルモード（`--local`）でのクライアントサイドパッチ適用
6. DryRunモード（client/server）でのシミュレーション実行
7. サブリソースへのパッチ適用（`--subresource` 指定時）

**画面遷移**：kubectl patchは単独で完結するコマンドであり、他のコマンドへの直接的な遷移はない。ただし、kubectl applyのワークフロー内でパッチ操作が内部的に利用される場合がある。また、kubectl editでの対話的編集の代替として利用されることが多い。

**権限による表示制御**：パッチ操作にはKubernetes RBACにおける対象リソースの `patch` 動詞（verb）に対する権限が必要である。権限不足の場合はAPI Serverからforbiddenエラーが返される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 85 | リソースパッチ（patch） | 主機能 | Strategic Merge PatchまたはJSON Patchでリソースを部分更新する主処理 |
| 1 | API Serverコア | API連携 | パッチリクエストをAPI Serverに送信する |

## 画面種別

CLI コマンド（リソース更新操作）

## URL/ルーティング

```
kubectl patch (-f FILENAME | TYPE NAME) [-p PATCH|--patch-file FILE]
```

コマンドエントリーポイント: `staging/src/k8s.io/kubectl/pkg/cmd/patch/patch.go` の `NewCmdPatch` 関数（行117）

## 入出力項目

### 入力パラメータ（フラグ）

| パラメータ名 | 短縮形 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|--------|-----|------|-------------|------|
| --patch | -p | string | *1 | "" | リソースJSONファイルに適用するパッチ内容 |
| --patch-file | - | string | *1 | "" | パッチ内容を含むファイルパス |
| --type | - | string | No | "strategic" | パッチタイプ（json / merge / strategic） |
| --local | - | bool | No | false | trueの場合、サーバーサイドではなくファイルの内容に対してパッチを適用 |
| --dry-run | - | string | No | "none" | DryRun戦略（none / client / server） |
| -f / --filename | -f | []string | *2 | - | リソースを特定するファイル名 |
| --subresource | - | string | No | "" | パッチ対象のサブリソース |
| --field-manager | - | string | No | "kubectl-patch" | サーバーサイドApply用のフィールドマネージャー名 |
| -o / --output | -o | string | No | "" | 出力形式（json / yaml / name 等） |
| --record | - | bool | No | false | 変更をアノテーションに記録する（非推奨） |

*1: `--patch` と `--patch-file` のいずれか一方が必須（両方指定は不可）
*2: TYPE NAME形式で指定しない場合に必須

### 位置引数

| 引数 | 必須 | 説明 |
|------|------|------|
| TYPE | *2 | リソースタイプ（pod, deployment, node 等） |
| NAME | *2 | リソース名 |

## 表示項目

### 成功時の出力

| 項目 | 形式 | 説明 |
|------|------|------|
| リソース種別/名前 | テキスト | パッチ適用後のリソース情報（例: `deployment.apps/nginx patched`） |
| パッチ状態 | テキスト | "patched" または "patched (no change)" |

### 出力形式オプション指定時

| 出力形式 | 説明 |
|----------|------|
| json | パッチ適用後のリソースをJSON形式で出力 |
| yaml | パッチ適用後のリソースをYAML形式で出力 |
| name | リソース名のみ出力 |

## イベント仕様

### 1-パッチ実行

1. コマンド引数とフラグのパース（`Complete` メソッド、行149）
2. バリデーション実行（`Validate` メソッド、行181）
   - `--patch` と `--patch-file` の排他チェック
   - `--local` とサーバーリソース指定の排他チェック
   - `--type` の有効値チェック（json / merge / strategic）
3. パッチバイト列の取得（ファイルまたはインライン）（行208-217）
4. YAML入力の場合、JSON形式に変換（行219-222）
5. resource.Builderによるリソース情報の構築（行224-233）
6. 各リソースに対するVisitor関数でパッチ適用（行240-308）

### 2-サーバーサイドパッチ（非ローカル・非DryRunClient）

1. RESTMappingからクライアントを取得（行249）
2. `resource.Helper.Patch` でAPI Serverにパッチリクエスト送信（行259）
3. 変更があったかを `reflect.DeepEqual` で判定（行267）
4. レコーダーによる変更記録（MergePatch形式）（行270-278）
5. 結果の出力（行280-284）

### 3-ローカルパッチ（--local または --dry-run=client）

1. オブジェクトをJSONにシリアライズ（行287）
2. `getPatchedJSON` でパッチタイプに応じたローカルパッチ適用（行292）
3. 結果をデシリアライズして出力（行297-307）

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| パッチ実行 | etcd（対象リソース） | UPDATE（PATCH） | 指定されたパッチタイプに基づきリソースのフィールドを部分更新 |

### テーブル別更新項目詳細

#### etcd（対象Kubernetesリソース）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| PATCH | パッチで指定されたフィールド | パッチ内容に基づく | Strategic Merge Patchはリスト項目のマージキーを考慮 |
| PATCH | metadata.annotations (kubectl.kubernetes.io/last-applied-configuration) | --recordフラグ指定時に更新 | 非推奨機能 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 発生条件 |
|-------------|------|--------------|----------|
| MSG-P01 | 成功 | `{type}/{name} patched` | パッチが正常に適用された場合 |
| MSG-P02 | 成功 | `{type}/{name} patched (no change)` | パッチ適用したが変更がなかった場合 |
| MSG-P03 | エラー | `cannot specify --patch and --patch-file together` | 両方のフラグが指定された場合 |
| MSG-P04 | エラー | `must specify --patch or --patch-file containing the contents of the patch` | パッチ内容が未指定の場合 |
| MSG-P05 | エラー | `cannot specify --local and server resources` | --localと位置引数の同時指定 |
| MSG-P06 | エラー | `cannot specify --local and --dry-run=server` | --localと--dry-run=serverの同時指定 |
| MSG-P07 | エラー | `--type must be one of [json merge strategic], not "{value}"` | 無効なパッチタイプ指定 |
| MSG-P08 | エラー | `{patchType} is not supported by {GVK}` | サポートされないパッチタイプ |
| MSG-P09 | エラー | `no objects passed to patch` | パッチ対象リソースが0件の場合 |
| MSG-P10 | エラー | `unable to read patch file: {error}` | パッチファイル読み取り失敗 |
| MSG-P11 | エラー | `unable to parse "{patch}": {error}` | パッチ内容のJSONパース失敗 |

## 例外処理

| 例外 | 発生条件 | 処理内容 |
|------|----------|----------|
| UnsupportedMediaType | パッチタイプがリソースでサポートされない | エラーメッセージを表示して終了 |
| 権限不足（Forbidden） | RBACでpatch権限がない | API Serverからのエラーメッセージを表示 |
| リソース未発見（NotFound） | 指定リソースが存在しない | API Serverからの404エラーを表示 |
| コンフリクト（Conflict） | resourceVersionが不一致 | 競合エラーメッセージを表示 |
| パースエラー | YAML/JSONのパース失敗 | パース失敗のエラーメッセージを表示 |
| Strategic Merge Patchの非サポート | カスタムリソースにStrategic Merge Patchを使用 | "strategic merge patch is not supported for {GVK} locally, try --type merge" |

## 備考

- Strategic Merge Patchはカスタムリソースではサポートされていない。カスタムリソースには `--type merge` または `--type json` を使用する必要がある。
- `--subresource` フラグにより、scaleサブリソースなど特定のサブリソースに対するパッチが可能。
- パッチ入力としてYAML形式も受け付けるが、内部的にはJSONに変換されて処理される。
- `--local` フラグ使用時はAPI Serverへの接続なしにパッチ結果をプレビューできる。

---

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

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

### 推奨読解順序

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

パッチコマンドの中心的なデータ構造である `PatchOptions` を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | patch.go | `staging/src/k8s.io/kubectl/pkg/cmd/patch/patch.go` | PatchOptions構造体（行54-78）の各フィールドの役割を理解する |
| 1-2 | types.go | `staging/src/k8s.io/apimachinery/pkg/types/patch.go` | PatchType定数（JSONPatchType, MergePatchType, StrategicMergePatchType）の定義 |

**読解のコツ**: `patchTypes` マップ（行50）でユーザー入力文字列とPatchType定数の対応関係を確認する。

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

処理の起点となる `NewCmdPatch` 関数からコマンド登録の流れを追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | patch.go | `staging/src/k8s.io/kubectl/pkg/cmd/patch/patch.go` | NewCmdPatch関数（行117-147）でcobraコマンドの登録、フラグの定義を確認 |

**主要処理フロー**:
1. **行117**: `NewCmdPatch` 関数 - cobraコマンド生成
2. **行127-131**: Run関数 - Complete -> Validate -> RunPatchの順で実行
3. **行137-144**: フラグ登録（--patch, --patch-file, --type, --local, --subresource等）

#### Step 3: Complete/Validateフェーズを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | patch.go | `staging/src/k8s.io/kubectl/pkg/cmd/patch/patch.go` | Complete関数（行149-179）でFactory経由のNamespace取得、Builder初期化 |
| 3-2 | patch.go | `staging/src/k8s.io/kubectl/pkg/cmd/patch/patch.go` | Validate関数（行181-200）で入力パラメータの整合性チェック |

**主要処理フロー**:
- **行170**: `f.ToRawKubeConfigLoader().Namespace()` - kubeconfig からNamespace取得
- **行182-187**: --patchと--patch-fileの排他チェック
- **行194-198**: --typeの有効値チェック

#### Step 4: RunPatch - メイン処理ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | patch.go | `staging/src/k8s.io/kubectl/pkg/cmd/patch/patch.go` | RunPatch関数（行202-316）のサーバーサイド/ローカルパッチの分岐処理 |
| 4-2 | patch.go | `staging/src/k8s.io/kubectl/pkg/cmd/patch/patch.go` | getPatchedJSON関数（行318-350）のパッチタイプ別ローカル処理 |

**主要処理フロー**:
- **行203-206**: パッチタイプの決定
- **行208-222**: パッチバイト列の取得とJSON変換
- **行224-233**: resource.Builderによるリソース情報構築
- **行247-284**: サーバーサイドパッチ処理（helper.Patch呼び出し）
- **行287-307**: ローカルパッチ処理（getPatchedJSON呼び出し）

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

```
NewCmdPatch (行117)
    │
    ├─ Complete (行149)
    │      ├─ RecordFlags.Complete
    │      ├─ GetDryRunStrategy
    │      └─ f.NewBuilder()
    │
    ├─ Validate (行181)
    │      └─ パラメータ整合性チェック
    │
    └─ RunPatch (行202)
           ├─ yaml.ToJSON (行219)
           ├─ builder.Do() (行224-233)
           └─ r.Visit() (行240)
                  ├─ [サーバーサイド] helper.Patch (行259)
                  │      └─ Recorder.MakeRecordMergePatch (行270)
                  └─ [ローカル] getPatchedJSON (行292)
                         ├─ jsonpatch.DecodePatch (JSONPatch, 行321)
                         ├─ jsonpatch.MergePatch (MergePatch, 行336)
                         └─ strategicpatch.StrategicMergePatch (Strategic, 行344)
```

### データフロー図

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

パッチ内容                 ┌──────────────────┐
(-p / --patch-file) ──────▶│ yaml.ToJSON変換   │
                          └────────┬─────────┘
                                   │
リソース指定               ┌──────────────────┐
(TYPE NAME / -f) ─────────▶│ resource.Builder  │
                          └────────┬─────────┘
                                   │
                          ┌────────▼─────────┐
                          │  パッチ適用判定    │
                          │ (Local/Server)    │
                          └────────┬─────────┘
                                   │
                    ┌──────────────┴──────────────┐
                    │                              │
           ┌───────▼────────┐            ┌────────▼────────┐
           │ helper.Patch    │            │ getPatchedJSON   │
           │ (API Server)   │            │ (ローカル)        │
           └───────┬────────┘            └────────┬────────┘
                   │                              │
                   └──────────┬───────────────────┘
                              │
                     ┌────────▼────────┐
                     │ PrintObj        │──────▶ 標準出力
                     └─────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| patch.go | `staging/src/k8s.io/kubectl/pkg/cmd/patch/patch.go` | ソース | patchコマンドのメイン実装（358行） |
| types.go | `staging/src/k8s.io/apimachinery/pkg/types/patch.go` | ソース | PatchType定数の定義 |
| strategicpatch | `staging/src/k8s.io/apimachinery/pkg/util/strategicpatch/` | ソース | Strategic Merge Patchロジック |
| json-patch | `vendor/gopkg.in/evanphx/json-patch.v4/` | ベンダー | JSON PatchおよびMerge Patchライブラリ |
| resource/helper.go | `staging/src/k8s.io/cli-runtime/pkg/resource/helper.go` | ソース | API Serverへのリクエストヘルパー |
| yaml.go | `staging/src/k8s.io/apimachinery/pkg/util/yaml/` | ソース | YAML-JSON変換ユーティリティ |
| completion.go | `staging/src/k8s.io/kubectl/pkg/util/completion/completion.go` | ソース | シェル補完用のリソースタイプ・名前補完関数 |
