# 機能設計書 42-ノード管理コマンド

## 概要

本ドキュメントは、JenkinsのCLI（コマンドラインインターフェース）を通じてノード（エージェント）を操作するためのノード管理コマンド群の機能設計を記載する。

### 本機能の処理概要

ノード管理コマンドは、CLIからJenkinsのノード（ビルドエージェント）を作成、削除、接続、切断、オンライン/オフライン切り替え、設定取得・更新、状態待機を行うための機能を提供する。

**業務上の目的・背景**：大規模なCI/CD環境では、多数のビルドエージェントを管理する必要がある。スクリプトによるエージェントのプロビジョニング自動化、メンテナンス時の一括オフライン化、インフラストラクチャ・アズ・コードによるノード構成管理などのユースケースに対応するため、CLIベースのノード管理機能が必要である。

**機能の利用シーン**：
- 新規ビルドエージェントの自動プロビジョニング
- メンテナンス作業前の複数ノード一括オフライン化
- 障害発生時のノード再接続スクリプト
- インフラストラクチャ・アズ・コードでのノード構成管理
- 自動スケーリングシステムとの連携

**主要な処理内容**：
1. `create-node`: 標準入力からXML設定を読み込み、新規ノードを作成
2. `delete-node`: 指定したノードを削除（複数指定可能）
3. `connect-node`: 指定したノードへの接続を開始（複数指定可能）
4. `disconnect-node`: 指定したノードを切断（複数指定可能）
5. `online-node`: 指定したノードをオンライン状態に変更（複数指定可能）
6. `offline-node`: 指定したノードをオフライン状態に変更（複数指定可能）
7. `get-node`: 指定したノードのXML設定を標準出力に出力
8. `update-node`: 標準入力からXML設定を読み込み、既存ノードを更新
9. `wait-node-online`: ノードがオンラインになるまで待機
10. `wait-node-offline`: ノードがオフラインになるまで待機

**関連システム・外部連携**：Jenkins CLI クライアント（jenkins-cli.jar）またはSSH経由でコマンドを実行。クラウドプロビジョニングシステムや構成管理ツール（Ansible、Terraform等）との連携で使用される。

**権限による制御**：ノード作成にはComputer.CREATE、削除にはComputer.DELETE、接続/切断/オンライン/オフラインにはComputer.CONNECTまたはComputer.DISCONNECT権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 59 | CLI操作 | 主画面 | CLI使用方法とコマンド一覧の表示、ノード管理コマンドの説明 |

## 機能種別

CRUD操作 / ノード状態制御 / コマンド実行

## 入力仕様

### 入力パラメータ

#### create-node コマンド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| nodeName | String | No | ノード名（省略時はXML内の名前を使用） | 同名ノードが存在しないこと |
| stdin | InputStream | Yes | ノード設定XML | 有効なXML形式、Nodeオブジェクトとしてデシリアライズ可能 |

#### delete-node コマンド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| nodes | List<String> | Yes | 削除対象ノード名のリスト | 各ノードが存在すること |

#### connect-node コマンド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| nodes | List<String> | Yes | 接続対象ノード名のリスト | 各ノードが存在すること |
| -f (force) | boolean | No | 接続中の場合キャンセルしてリトライ | - |

#### disconnect-node コマンド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| nodes | List<String> | Yes | 切断対象ノード名のリスト | 各ノードが存在すること |
| -m (message) | String | No | 切断理由メッセージ | - |

#### offline-node コマンド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| nodes | List<String> | Yes | オフライン対象ノード名のリスト | 各ノードが存在すること |
| -m (message) | String | No | オフライン理由メッセージ | - |

#### online-node コマンド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| nodes | List<String> | Yes | オンライン対象ノード名のリスト | 各ノードが存在すること |

### 入力データソース

- CLI経由でのコマンドライン引数
- 標準入力（create-node/update-nodeの場合はXML設定ファイル）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| stdout | String | コマンド実行結果（get-nodeの場合はXML） |
| stderr | String | エラーメッセージ |
| returnCode | int | 0=成功、非0=エラー |

### 出力先

- 標準出力（コマンド実行結果）
- 標準エラー出力（エラーメッセージ）
- Jenkinsファイルシステム（ノード設定ファイルの作成・更新・削除）

## 処理フロー

### 処理シーケンス

#### create-node

```
1. 権限チェック
   └─ Computer.CREATE権限を確認
2. XMLからNodeオブジェクト生成
   └─ Jenkins.XSTREAM2.fromXML(stdin)
3. ノード名設定（オプション）
   └─ コマンドライン引数で指定された場合は上書き
4. ノード存在チェック
   └─ 同名ノードが存在する場合はエラー
5. ノード追加
   └─ jenkins.addNode(newNode)
```

#### connect-node

```
1. ノード名リスト取得（重複除去）
2. 各ノードに対してループ
   └─ Computer.resolveForCLI()でComputerオブジェクト取得
   └─ computer.cliConnect(force)を実行
3. エラー集約
   └─ 複数ノードでエラーがあれば集約してAbortException
```

#### offline-node

```
1. ノード名リスト取得（重複除去）
2. 各ノードに対してループ
   └─ jenkins.getComputer()でComputerオブジェクト取得
   └─ ノード不存在時は類似名を提案
   └─ computer.cliOffline(cause)を実行
3. エラー集約
   └─ 複数ノードでエラーがあれば集約してAbortException
```

### フローチャート

```mermaid
flowchart TD
    A[CLIコマンド受信] --> B{コマンド種別判定}

    B -->|create-node| C[権限チェック]
    C --> D[XMLからNode生成]
    D --> E{ノード名指定あり?}
    E -->|Yes| F[ノード名を上書き]
    E -->|No| G[XML内の名前を使用]
    F --> H{同名ノード存在?}
    G --> H
    H -->|No| I[ノード追加]
    H -->|Yes| J[エラー: ノード既存]
    I --> K[成功: return 0]

    B -->|connect/disconnect/online/offline| L[ノードリスト取得]
    L --> M[各ノードをループ]
    M --> N{ノード存在?}
    N -->|Yes| O[状態変更処理]
    N -->|No| P[エラー記録 + 類似名提案]
    O --> Q{全ノード処理完了?}
    P --> Q
    Q -->|No| M
    Q -->|Yes| R{エラーあり?}
    R -->|Yes| S[AbortException]
    R -->|No| K

    B -->|delete-node| T[ノードリスト取得]
    T --> U[各ノードをループ]
    U --> V{ノード存在?}
    V -->|Yes| W[ノード削除]
    V -->|No| X[エラー記録]
    W --> Y{全ノード処理完了?}
    X --> Y
    Y -->|No| U
    Y -->|Yes| R
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-42-01 | ノード名重複禁止 | 同名のノードは作成不可 | create-node |
| BR-42-02 | 複数ノード一括処理 | delete/connect/disconnect/online/offlineは複数ノードを一度に処理可能 | 該当コマンド |
| BR-42-03 | エラー継続処理 | 複数ノード処理時、一部でエラーが発生しても残りを継続処理 | 複数ノード処理コマンド |
| BR-42-04 | 類似名提案 | 存在しないノード名が指定された場合、類似名を提案 | disconnect-node, offline-node |
| BR-42-05 | 空文字でマスターノード指定 | ノード名に空文字を指定するとビルトインノード（マスター）を対象とする | connect/disconnect/online/offline |

### 計算ロジック

該当なし

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

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

Jenkinsはファイルベースでノード設定を管理するため、データベース操作ではなくファイルシステム操作となる。

| 操作 | 対象ファイル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| create-node | $JENKINS_HOME/nodes/{name}/config.xml | CREATE | ノード設定ファイル作成 |
| delete-node | $JENKINS_HOME/nodes/{name}/ | DELETE | ノードディレクトリ削除 |
| update-node | $JENKINS_HOME/nodes/{name}/config.xml | UPDATE | ノード設定ファイル更新 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IllegalStateException | ノード既存 | create-nodeで同名ノードが存在 | 別名を指定するか既存ノードを削除 |
| IllegalArgumentException | ノード不存在 | 指定ノードが存在しない | ノード名を確認（類似名が提案される場合あり） |
| AccessDeniedException | 権限不足 | 必要な権限がない | 管理者に権限付与を依頼 |
| AbortException | 一括処理エラー | 複数ノード処理で一部エラー発生 | stderrのエラーメッセージを確認 |

### リトライ仕様

- connect-nodeの`-f`オプションで、接続処理中の場合にキャンセルしてリトライ可能
- その他のコマンドはステートレスなため、クライアント側でリトライを実装

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

Jenkinsのノード操作はファイルシステムベースであり、トランザクション制御は行われない。複数ノードの一括処理時に途中でエラーが発生した場合、処理済みのノードは変更されたままとなる。

## パフォーマンス要件

- 単一ノードの作成/削除/状態変更: 1秒以内
- 複数ノードの一括処理: ノード数に比例（1ノードあたり1秒程度）

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

- 各コマンドは対応するJenkins権限（Computer.CREATE, Computer.DELETE, Computer.CONNECT, Computer.DISCONNECT）をチェック
- Jenkins.ADMINISTER権限を持つユーザーは全操作が可能
- CLI認証はAPIトークンまたはSSH公開鍵認証を使用
- ノード設定XMLに含まれる機密情報（秘密鍵等）は適切に保護

## 備考

- ビルトインノード（マスター）は空文字で指定可能（connect/disconnect/online/offlineコマンド）
- ノード不存在時にEditDistanceアルゴリズムで類似名を提案
- クラウドプロビジョニングされたノードも同様に管理可能

---

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

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

### 推奨読解順序

#### Step 1: CLIコマンド基盤を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CLICommand.java | `core/src/main/java/hudson/cli/CLICommand.java` | 全CLIコマンドの基底クラス |

#### Step 2: 各ノード管理コマンドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CreateNodeCommand.java | `core/src/main/java/hudson/cli/CreateNodeCommand.java` | ノード作成の実装 |
| 2-2 | DeleteNodeCommand.java | `core/src/main/java/hudson/cli/DeleteNodeCommand.java` | ノード削除の実装 |
| 2-3 | ConnectNodeCommand.java | `core/src/main/java/hudson/cli/ConnectNodeCommand.java` | ノード接続の実装 |
| 2-4 | DisconnectNodeCommand.java | `core/src/main/java/hudson/cli/DisconnectNodeCommand.java` | ノード切断の実装 |
| 2-5 | OnlineNodeCommand.java | `core/src/main/java/hudson/cli/OnlineNodeCommand.java` | オンライン化の実装 |
| 2-6 | OfflineNodeCommand.java | `core/src/main/java/hudson/cli/OfflineNodeCommand.java` | オフライン化の実装 |

**主要処理フロー（CreateNodeCommand）**:
- **52-53行目**: 権限チェック（Computer.CREATE）
- **55行目**: XMLからNodeオブジェクト生成
- **57-61行目**: コマンドライン引数でノード名上書き
- **63-64行目**: 同名ノード存在チェック
- **67行目**: jenkins.addNode()でノード追加

**主要処理フロー（ConnectNodeCommand）**:
- **61行目**: 重複除去のためHashSet使用
- **63-76行目**: 各ノードに対するループ処理
- **65行目**: Computer.resolveForCLI()でComputerオブジェクト取得
- **66行目**: cliConnect(force)で接続実行

**主要処理フロー（OfflineNodeCommand）**:
- **66-67行目**: ノード存在チェックと類似名提案
- **71-72行目**: EditDistance.findNearest()による類似名検索
- **76行目**: computer.cliOffline(cause)でオフライン化

#### Step 3: Computerモデルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Computer.java | `core/src/main/java/hudson/model/Computer.java` | ノードの実行環境クラス、cliConnect/cliDisconnect/cliOnline/cliOfflineメソッド |
| 3-2 | Node.java | `core/src/main/java/hudson/model/Node.java` | ノードの基底クラス |
| 3-3 | ComputerSet.java | `core/src/main/java/hudson/model/ComputerSet.java` | ノード一覧管理クラス |

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

```
CLI Client (jenkins-cli.jar)
    │
    └─ CLICommand (基底クラス)
           │
           ├─ CreateNodeCommand
           │      ├─ Jenkins.checkPermission(Computer.CREATE)
           │      ├─ Jenkins.XSTREAM2.fromXML() - XMLパース
           │      ├─ Node.setNodeName() - 名前設定
           │      ├─ Jenkins.getNode() - 存在チェック
           │      └─ Jenkins.addNode() - ノード追加
           │
           ├─ DeleteNodeCommand
           │      ├─ Jenkins.getNode() - ノード取得
           │      └─ Computer.doDoDelete() - ノード削除
           │
           ├─ ConnectNodeCommand
           │      ├─ Computer.resolveForCLI() - Computer取得
           │      └─ Computer.cliConnect() - 接続実行
           │
           ├─ DisconnectNodeCommand
           │      ├─ Jenkins.getComputer() - Computer取得
           │      ├─ EditDistance.findNearest() - 類似名検索
           │      └─ Computer.cliDisconnect() - 切断実行
           │
           ├─ OnlineNodeCommand
           │      ├─ Computer.resolveForCLI() - Computer取得
           │      └─ Computer.cliOnline() - オンライン化
           │
           └─ OfflineNodeCommand
                  ├─ Jenkins.getComputer() - Computer取得
                  ├─ EditDistance.findNearest() - 類似名検索
                  └─ Computer.cliOffline() - オフライン化
```

### データフロー図

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

CLIコマンド引数 ──────▶ CLICommand.run() ──────────────────▶ return code (0/非0)
                              │
標準入力 (XML) ──────▶ CreateNodeCommand ─────────────────▶ ノード設定ファイル
                              │                                   (config.xml)
                              ├─ ConnectNodeCommand ─────────────▶ エージェント接続開始
                              │
                              ├─ DisconnectNodeCommand ──────────▶ エージェント切断
                              │
                              ├─ OnlineNodeCommand ──────────────▶ ノードオンライン化
                              │
                              └─ OfflineNodeCommand ─────────────▶ ノードオフライン化
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CLICommand.java | `core/src/main/java/hudson/cli/CLICommand.java` | ソース | CLI基底クラス |
| CreateNodeCommand.java | `core/src/main/java/hudson/cli/CreateNodeCommand.java` | ソース | ノード作成コマンド |
| DeleteNodeCommand.java | `core/src/main/java/hudson/cli/DeleteNodeCommand.java` | ソース | ノード削除コマンド |
| ConnectNodeCommand.java | `core/src/main/java/hudson/cli/ConnectNodeCommand.java` | ソース | ノード接続コマンド |
| DisconnectNodeCommand.java | `core/src/main/java/hudson/cli/DisconnectNodeCommand.java` | ソース | ノード切断コマンド |
| OnlineNodeCommand.java | `core/src/main/java/hudson/cli/OnlineNodeCommand.java` | ソース | オンライン化コマンド |
| OfflineNodeCommand.java | `core/src/main/java/hudson/cli/OfflineNodeCommand.java` | ソース | オフライン化コマンド |
| GetNodeCommand.java | `core/src/main/java/hudson/cli/GetNodeCommand.java` | ソース | ノード設定取得コマンド |
| UpdateNodeCommand.java | `core/src/main/java/hudson/cli/UpdateNodeCommand.java` | ソース | ノード設定更新コマンド |
| WaitNodeOnlineCommand.java | `core/src/main/java/hudson/cli/WaitNodeOnlineCommand.java` | ソース | オンライン待機コマンド |
| WaitNodeOfflineCommand.java | `core/src/main/java/hudson/cli/WaitNodeOfflineCommand.java` | ソース | オフライン待機コマンド |
| Computer.java | `core/src/main/java/hudson/model/Computer.java` | ソース | ノード実行環境クラス |
| Node.java | `core/src/main/java/hudson/model/Node.java` | ソース | ノード基底クラス |
| EditDistance.java | `core/src/main/java/hudson/util/EditDistance.java` | ソース | 類似名検索ユーティリティ |
