# 機能設計書 107-リソース置換（replace）

## 概要

本ドキュメントは、`kubectl replace` コマンドによるリソース置換機能の設計を記述する。マニフェストファイルに基づいてリソースを完全に置換（上書き更新）する。

### 本機能の処理概要

**業務上の目的・背景**：`kubectl apply` がマージベースの部分更新であるのに対し、`kubectl replace` はリソース仕様を完全に置き換える。マニフェストファイルに記述された内容で既存リソースを完全に上書きするため、マニフェストを唯一の情報源（Single Source of Truth）とする運用に適している。

**機能の利用シーン**：マニフェストファイルでリソースを完全管理する場合、フィールドの削除を含む更新が必要な場合、`--force` フラグによるリソースの再作成（削除後作成）が必要な場合に利用される。

**主要な処理内容**：
1. マニフェストファイルの読み込みとパース
2. 通常置換: API ServerへのPUT（Replace）リクエスト
3. 強制置換（--force）: リソース削除 -> 削除完了待機 -> 再作成
4. Raw URI置換: 指定URIへのPUTリクエスト
5. バリデーションとアノテーション管理

**関連システム・外部連携**：API Server（PUT/DELETE/POST）

**権限による制御**：対象リソースのupdate権限（通常）、delete+create権限（--force時）が必要

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | kubectl replace | 主機能 | マニフェストに基づくリソースの完全置換 |

## 機能種別

リソース更新・再作成

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -f / --filename | string[] | Yes | マニフェストファイル | 必須 |
| --force | bool | No | 強制置換（削除後再作成） | --dry-run と排他 |
| --grace-period | int | No | 削除猶予期間（秒） | --force 指定時のみ有効 |
| --timeout | duration | No | 削除待機タイムアウト | --force 指定時のみ有効、デフォルト: 5分 |
| --cascade | string | No | カスケード削除設定 | background/orphan/foreground |
| --dry-run | string | No | ドライラン | client/server、--force と排他 |
| --raw | string | No | Raw URI指定 | 単一ファイルのみ、URLファイル不可 |
| --validate | string | No | バリデーション設定 | strict/warn/ignore |
| --subresource | string | No | サブリソース指定 | |
| --field-manager | string | No | フィールドマネージャー | デフォルト: "kubectl-replace" |

### 入力データソース

- マニフェストファイル（YAML/JSON）
- 標準入力（stdin）
- Kustomizeディレクトリ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 処理結果 | text | "replaced" メッセージ |

### 出力先

標準出力（stdout）

## 処理フロー

### 処理シーケンス

```
1. 引数パースとバリデーション（Complete + Validate）
   ├─ ファイル指定必須チェック
   ├─ --grace-period は --force 必須チェック
   ├─ --timeout は --force 必須チェック
   ├─ --force と --dry-run は排他チェック
   └─ --raw の制約チェック
2. 処理分岐
   ├─ [--raw] rawhttp.RawPut()
   ├─ [--force] forceReplace()
   └─ [通常] Resource Replace
3. [通常] Replace処理
   ├─ Builder.Unstructured().FilenameParam().Do()
   ├─ CreateOrUpdateAnnotation()
   ├─ NewHelper().Replace()
   └─ PrintObj()
4. [--force] 強制置換処理
   ├─ Builder でリソース取得
   ├─ DeleteOptions.DeleteResult() でリソース削除
   ├─ PollUntilContextTimeout() で削除完了待機（1秒間隔）
   ├─ Builder でリソース再取得
   ├─ NewHelper().Create() でリソース再作成
   └─ PrintObj()
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[引数パース・バリデーション]
    B --> C{モード判定}
    C -->|--raw| D[RawPut]
    C -->|--force| E[forceReplace]
    C -->|通常| F[通常Replace]
    D --> G[終了]
    E --> H[リソース削除]
    H --> I[削除完了待機 1秒間隔]
    I --> J[リソース再作成]
    J --> K[PrintObj]
    F --> L[Builder.Do]
    L --> M[アノテーション設定]
    M --> N[Helper.Replace PUT]
    N --> O[PrintObj]
    K --> G
    O --> G
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-701 | 完全置換 | PUT APIでリソースを完全に上書き | 通常モード |
| BR-702 | 強制置換 | 削除後に再作成する2段階操作 | --force 指定時 |
| BR-703 | grace-period=0 保護 | --grace-period=0 は自動的に1に変換し、waitForDeletion=true | 後方互換性のため |
| BR-704 | 削除待機タイムアウト | --force時のデフォルトタイムアウトは5分 | --force + timeout未指定時 |
| BR-705 | stdin処理 | stdinはテンポラリファイルに保存して2回目のBuilder使用に備える | --force + stdin使用時 |
| BR-706 | --raw制約 | 単一ローカルファイルのみ、URLファイル不可、--recursiveと排他 | --raw指定時 |
| BR-707 | バリデーション | Factory.Validator()によるスキーマバリデーション | 通常モード |

### 計算ロジック

強制置換でのstdin処理: 標準入力をテンポラリファイルに保存し、削除用と再作成用の2つのBuilderで利用する。テンポラリディレクトリはdefer os.RemoveAll()で確実に削除される。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 通常置換 | etcd（API Server経由） | UPDATE（PUT） | リソースの完全置換 |
| 強制削除 | etcd（API Server経由） | DELETE | リソースの削除 |
| 強制再作成 | etcd（API Server経由） | INSERT（POST） | リソースの新規作成 |
| Raw PUT | API Server | UPDATE（PUT） | 指定URIへのPUTリクエスト |

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

通常置換はPUT APIを使用し、リソースの全フィールドを上書きする。resourceVersionの一致が必要。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ファイル未指定 | -f未指定 | "must specify --filename to replace" |
| - | 排他制約 | --force + --dry-run | "--dry-run can not be used when --force is set" |
| - | grace-period制約 | --grace-period指定、--force未指定 | "--grace-period must have --force specified" |
| - | 空オブジェクト | --forceで0件 | "no objects passed to replace" |
| - | 削除待機タイムアウト | --force時に削除が完了しない | コンテキストタイムアウト |
| - | バリデーションエラー | スキーマ不整合 | バリデーションエラーメッセージ |

### リトライ仕様

強制置換時の削除待機は、1秒間隔でPollUntilContextTimeoutを使用。デフォルトタイムアウト5分。

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

強制置換（削除+再作成）は原子的でない2段階操作。削除完了後に再作成する。削除と再作成の間にダウンタイムが発生する。

## パフォーマンス要件

特に定義なし。リソース数に比例するAPIコール。

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

- 通常モードではupdate権限が必要
- --forceモードではdelete+create権限が必要
- --raw は任意のAPI URIへのPUTを可能にするため、慎重に使用すべき

## 備考

- `kubectl apply` との違い: replaceはPUT（完全上書き）、applyはPATCH（マージ）
- --force 使用時は一時的にリソースが存在しない期間が生じるため、本番環境での使用は慎重に行うべき
- --grace-period=0 はデータ損失を防ぐため自動的に1に変換される（後方互換性維持）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | replace.go | `staging/src/k8s.io/kubectl/pkg/cmd/replace/replace.go` | ReplaceOptions構造体（71-100行目）：コマンドオプション |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | replace.go | `staging/src/k8s.io/kubectl/pkg/cmd/replace/replace.go` | NewCmdReplace関数（111-140行目）：コマンド定義 |

#### Step 3: 通常置換処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | replace.go | `staging/src/k8s.io/kubectl/pkg/cmd/replace/replace.go` | Run関数（253-313行目）：通常置換メイン処理 |
| 3-2 | replace.go | `staging/src/k8s.io/kubectl/pkg/cmd/replace/replace.go` | **299-305行目**: NewHelper().Replace() - PUT APIの実行 |

#### Step 4: 強制置換処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | replace.go | `staging/src/k8s.io/kubectl/pkg/cmd/replace/replace.go` | forceReplace関数（315-423行目）：強制置換処理 |
| 4-2 | replace.go | `staging/src/k8s.io/kubectl/pkg/cmd/replace/replace.go` | **317-332行目**: stdin のテンポラリファイル保存 |
| 4-3 | replace.go | `staging/src/k8s.io/kubectl/pkg/cmd/replace/replace.go` | **350行目**: DeleteResult() でリソース削除 |
| 4-4 | replace.go | `staging/src/k8s.io/kubectl/pkg/cmd/replace/replace.go` | **362行目**: PollUntilContextTimeout で削除完了待機 |
| 4-5 | replace.go | `staging/src/k8s.io/kubectl/pkg/cmd/replace/replace.go` | **404-407行目**: NewHelper().Create() で再作成 |

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

```
NewCmdReplace
    │
    ├─ ReplaceOptions.Complete()
    │      ├─ DeleteFlags.ToOptions()
    │      └─ Factory.Validator()
    │
    ├─ ReplaceOptions.Validate()
    │
    └─ ReplaceOptions.Run()
           ├─ [--raw] rawhttp.RawPut()
           ├─ [--force] forceReplace()
           │      ├─ Builder.Do() [リソース取得]
           │      ├─ DeleteOptions.DeleteResult() [削除]
           │      ├─ PollUntilContextTimeout() [削除待機]
           │      ├─ Builder.Do() [再取得]
           │      └─ NewHelper().Create() [再作成]
           └─ [通常] Builder.Do().Visit()
                  ├─ CreateOrUpdateAnnotation()
                  └─ NewHelper().Replace() [PUT]
```

### データフロー図

```
[通常置換]
マニフェストファイル ──▶ Builder ──▶ Replace (PUT) ──▶ API Server ──▶ stdout

[強制置換]
マニフェストファイル ──▶ Builder ──▶ Delete ──▶ API Server
                                                    │
                                          削除完了待機 (polling)
                                                    │
                          Builder ──▶ Create (POST) ──▶ API Server ──▶ stdout
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| replace.go | `staging/src/k8s.io/kubectl/pkg/cmd/replace/replace.go` | ソース | メインロジック：通常置換・強制置換 |
| replace_test.go | `staging/src/k8s.io/kubectl/pkg/cmd/replace/replace_test.go` | テスト | ユニットテスト |
