# 画面設計書 16-kubectl uncordon

## 概要

本ドキュメントは、Kubernetes CLIツール `kubectl uncordon` コマンドの画面設計書である。ノードをスケジュール可能な状態に戻し、新規Podの配置を再開するコマンドの仕様を記載する。

### 本画面の処理概要

`kubectl uncordon` コマンドは、指定したノードの `spec.unschedulable` フィールドを `false` に設定し、Kubernetesスケジューラーがそのノードに新しいPodを配置できるようにする。cordonまたはdrainの後のメンテナンス完了時に使用する。

**業務上の目的・背景**：ノードメンテナンスの完了後、ノードをクラスタのワークロード配置対象に復帰させる必要がある。uncordonはメンテナンスフローの最終段階として使用され、ノードの正常運用復帰を実現する。

**画面へのアクセス方法**：ターミナル上で `kubectl uncordon <ノード名>` を実行する。

**主要な操作・処理内容**：
1. 指定されたノードの現在の状態を確認する
2. ノードの`spec.unschedulable`を`false`に設定するパッチを適用する
3. 結果を標準出力に表示する

**画面遷移**：メンテナンスフローにおいて `kubectl cordon` -> `kubectl drain` -> メンテナンス作業 -> `kubectl uncordon` の最終ステップ。

**権限による表示制御**：nodeリソースに対するget/patch権限が必要。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 93 | ドレイン（drain） | 主機能 | ノードをスケジュール可能な状態に戻す処理 |
| 18 | Node Lifecycleコントローラー | API連携 | ノードの状態復帰後にNode Lifecycleコントローラーが状態を監視する |

## 画面種別

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

## URL/ルーティング

```
kubectl uncordon NODE
```

## 入出力項目

### 入力項目

| 項目名 | フラグ | 型 | 必須 | デフォルト | 説明 |
|--------|--------|------|------|-----------|------|
| ノード名 | 位置引数 | string | Yes(*) | - | uncordon対象のノード名 |
| ラベルセレクタ | -l, --selector | string | No | "" | ラベルによるノード選択 |
| Dry Run | --dry-run | string | No | "none" | "none" / "client" / "server" |

(*) ノード名または--selectorのいずれかが必須

### 出力項目

| 項目名 | 説明 |
|--------|------|
| 処理結果メッセージ | `node/<name> uncordoned` または `node/<name> already uncordoned` |

## 表示項目

| 項目 | 形式 | 説明 |
|------|------|------|
| ノード名 | `node/<name>` | 対象ノード |
| 操作結果 | `uncordoned` / `already uncordoned` | 実行結果 |

## イベント仕様

### 1-uncordon実行

1. コマンドライン引数を解析し、DrainCmdOptionsを初期化する（`Complete`、drain.go L243-322）
2. ノード名と--selectorの排他チェックを行う（L249-251）
3. Builderでノードリソースを取得する（L292-321）
4. 各ノードに対してRunCordonOrUncordon(false)を実行する（`RunCordonOrUncordon`、L402-458）
   - CordonHelperを作成する（L416）
   - ノードが既にuncordon済み（schedulable）か確認する（`UpdateIfRequired`、L422）
   - cordon状態の場合、PatchOrReplaceでノードを更新する（L431）
   - 結果メッセージを表示する

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

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

| 操作（イベント） | 対象リソース | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| uncordon実行 | Node | PATCH/UPDATE | spec.unschedulableをfalseに設定 |

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

#### Node

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| PATCH | spec.unschedulable | false | スケジュール可能状態に戻す |

## メッセージ仕様

| 種別 | メッセージ | 条件 |
|------|-----------|------|
| 成功 | `node/<name> uncordoned` | uncordon成功時 |
| 情報 | `node/<name> already uncordoned` | 既にスケジュール可能 |
| エラー | `USAGE: uncordon NODE [flags]` | 引数未指定 |
| エラー | `error: cannot specify both a node name and a --selector option` | 名前とセレクタの同時指定 |
| エラー | `error: unable to uncordon node "<name>": <error>` | uncordon処理失敗 |

## 例外処理

| 例外条件 | 動作 |
|---------|------|
| ノード名未指定かつセレクタ未指定 | 使用法エラーを表示して終了 |
| ノードが存在しない | NotFoundエラーを表示して終了 |
| パッチ適用失敗 | エラーメッセージを表示して次のノードに続行 |
| 権限不足 | 403 Forbiddenエラーを表示 |

## 備考

- uncordonはcordonと同一の`RunCordonOrUncordon`関数を使用し、引数`desired=false`で動作する（drain.go L107）
- CordonHelperが`UpdateIfRequired(false)`を呼び出し、spec.unschedulableがtrueの場合のみ更新を実行する
- cordonと同様に、dry-run=clientの場合はAPI Serverへのリクエストを送信しない

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | drain.go | `staging/src/k8s.io/kubectl/pkg/cmd/drain/drain.go` | DrainCmdOptions構造体（L44-55）：cordon/uncordon/drain共通 |

**読解のコツ**: uncordonの処理はcordonとほぼ同一。RunCordonOrUncordonのdesired引数がfalseになるだけの違い。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | drain.go | `staging/src/k8s.io/kubectl/pkg/cmd/drain/drain.go` | NewCmdUncordon関数（L95-113）：uncordonコマンド定義 |

**主要処理フロー**:
1. **L96**: NewDrainCmdOptionsでオプション初期化
2. **L105-108**: Complete -> RunCordonOrUncordon(false)の呼び出しチェーン
3. **L110-111**: --selectorと--dry-runフラグの登録

#### Step 3: コア処理を理解する

cordonと同一のComplete（L243-322）とRunCordonOrUncordon（L402-458）を参照。desired=falseの場合の動作に注目。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | drain.go | `staging/src/k8s.io/kubectl/pkg/cmd/drain/drain.go` | RunCordonOrUncordon（L402-458）：desired=falseでuncordon動作 |

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

```
NewCmdUncordon (L95)
    |
    +-- NewDrainCmdOptions (L149)
    |
    +-- Complete (L243)
    |       +-- f.KubernetesClientSet()
    |       +-- f.NewBuilder()
    |       +-- builder.ResourceNames("nodes", args...)
    |
    +-- RunCordonOrUncordon(false) (L402)
            +-- [各ノード]
                    +-- drain.NewCordonHelperFromRuntimeObject()
                    +-- c.UpdateIfRequired(false)
                    +-- c.PatchOrReplace()
                    +-- printer.PrintObj()
```

### データフロー図

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

ノード名 / --selector   Complete()
                       --> Builder.Do() ------------>+---> API Server
                       --> ノードリソース取得 ------->|     (Node取得)
                                                     |
                       RunCordonOrUncordon(false)    |
                       --> CordonHelper作成 -------->|
                       --> UpdateIfRequired(false) ->|
                       --> PatchOrReplace ---------->+---> API Server
                                                     |     (Node更新)
                                                     |
                                                     +---> stdout
                                                           "uncordoned"
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| drain.go | `staging/src/k8s.io/kubectl/pkg/cmd/drain/drain.go` | ソース | cordon/uncordon/drainコマンドの共通実装 |
| drain.go (pkg) | `staging/src/k8s.io/kubectl/pkg/drain/drain.go` | ソース | CordonHelper等のドレインユーティリティ |
| drain_test.go | `staging/src/k8s.io/kubectl/pkg/cmd/drain/drain_test.go` | テスト | drain関連コマンドのユニットテスト |
