# 画面設計書 23-ノード設定

## 概要

本ドキュメントは、Jenkins CI/CDサーバーにおける「ノード設定」画面の設計仕様を定義するものである。

### 本画面の処理概要

ノード設定画面は、特定のノード（エージェント）の設定を編集するための画面である。ノード名、リモートルートディレクトリ、ラベル、エグゼキュータ数、起動方法、保持戦略、ノードプロパティなど、ノードの動作に関わる各種設定を行う。この画面はNodeDescriptorに基づく動的なフォーム生成を行い、異なるノードタイプに応じた設定項目を提供する。

**業務上の目的・背景**：分散ビルド環境において、各ノードの特性（性能、用途、制約）に応じた適切な設定が必要である。この画面は、ノードの実行環境設定、ラベルによるジョブ割り当て制御、接続方法の設定、リソース管理などを一元的に行うためのインターフェースとして機能する。ノードの用途変更、性能調整、ラベル再編成などの運用作業を効率的に行うために必要な画面である。

**画面へのアクセス方法**：ノード詳細画面のサイドパネルから「Configure」リンクをクリック、またはノード一覧画面の設定アイコンをクリック、もしくは直接URL `/computer/{nodeName}/configure` でアクセスする。

**主要な操作・処理内容**：
1. ノード名の変更 - ノードの名前を編集（一意性チェックあり）
2. エグゼキュータ数の設定 - 並列実行可能なビルド数を設定
3. リモートルートディレクトリの設定 - エージェント上の作業ディレクトリを指定
4. ラベルの設定 - ノードに割り当てるラベル（スペース区切り）を設定
5. 使用方法の設定 - ジョブ実行の制限（可能な限り使用/ラベル制限のみ）
6. 起動方法の設定 - エージェントの接続方法（SSH、JNLP等）を選択・設定
7. 可用性の設定 - ノードのオンライン/オフラインスケジュール（RetentionStrategy）
8. ノードプロパティの設定 - 環境変数、ツールロケーション等の追加プロパティ
9. 保存 - 設定をファイルに保存

**画面遷移**：
- 遷移元：ノード詳細画面、ノード一覧画面
- 遷移先：ノード詳細画面（保存後）

**権限による表示制御**：
- Computer.EXTENDED_READ権限：設定画面の閲覧（読み取り専用モード）
- Computer.CONFIGURE権限：設定画面の編集・保存
- 読み取り専用モードではフォームは無効化され、保存ボタンは非表示

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 10 | エージェントノード | 主機能 | ノード設定の編集 |
| 12 | コンピューター管理 | 補助機能 | ノード接続設定 |
| 64 | フォームバリデーション | API連携 | 設定値の入力検証 |

## 画面種別

編集

## URL/ルーティング

- `/computer/{nodeName}/configure` - ノード設定画面

## 入出力項目

| 項目名 | 項目ID | 入出力 | 型 | 必須 | 説明 |
|--------|--------|--------|-----|------|------|
| ノード名 | name | 入力 | String | Yes | ノードの一意な識別名 |
| エグゼキュータ数 | numExecutors | 入力 | Integer | Yes | 並列実行可能なビルド数（1以上） |
| リモートルートディレクトリ | remoteFS | 入力 | String | Yes | エージェント上の作業ディレクトリパス |
| ラベル | labelString | 入力 | String | No | スペース区切りのラベル文字列 |
| 使用方法 | mode | 入力 | Enum | Yes | NORMAL（可能な限り使用）/ EXCLUSIVE（ラベル制限） |
| 起動方法 | launcher | 入力 | ComputerLauncher | Yes | エージェント起動方法の設定 |
| 可用性 | retentionStrategy | 入力 | RetentionStrategy | Yes | ノードのオンライン/オフライン戦略 |
| ノードプロパティ | nodeProperties | 入力 | List | No | 環境変数、ツール設定等 |

## 表示項目

| 項目名 | 項目ID | 型 | 説明 |
|--------|--------|-----|------|
| ページタイトル | title | String | 「Configure {nodeName}」形式のタイトル |
| 設定フォーム | form | Form | 各設定項目を含むフォーム |

## イベント仕様

### 1-Saveボタン押下

「Save」ボタン押下（POST configSubmit）により、入力された設定値をバリデーションし、問題がなければノード設定を保存する。保存完了後、ノード詳細画面へリダイレクトする。

### 2-Applyボタン押下

「Apply」ボタン押下（POST configSubmit + apply=true）により、画面遷移なしで設定を保存する。AJAXによる非同期保存が行われ、結果がメッセージとして表示される。

### 3-フォームバリデーション

各入力項目の変更時に、対応するdoCheck{FieldName}メソッドがAJAX呼び出しされ、リアルタイムでバリデーション結果が表示される。

### 4-起動方法の変更

起動方法（Launcher）のドロップダウン変更時に、選択されたLauncherタイプに応じた設定項目が動的に表示される。

### 5-可用性の変更

可用性（RetentionStrategy）のドロップダウン変更時に、選択されたStrategyタイプに応じた設定項目が動的に表示される。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Save/Apply | nodes/{nodeName}/config.xml | UPDATE | ノード設定ファイルの更新 |
| ノード名変更時 | nodes/ | RENAME | ノードディレクトリの名前変更 |

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

#### config.xml（ノード設定）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | name | フォーム入力値 | ノード名 |
| UPDATE | numExecutors | フォーム入力値 | エグゼキュータ数 |
| UPDATE | remoteFS | フォーム入力値 | リモートルートディレクトリ |
| UPDATE | labelString | フォーム入力値 | ラベル |
| UPDATE | mode | フォーム選択値 | 使用方法 |
| UPDATE | launcher | フォーム設定値（シリアライズ） | 起動方法 |
| UPDATE | retentionStrategy | フォーム設定値（シリアライズ） | 可用性 |
| UPDATE | nodeProperties | フォーム設定値（シリアライズ） | ノードプロパティ |

## メッセージ仕様

| メッセージID | メッセージ内容 | 表示条件 | 種別 |
|-------------|---------------|----------|------|
| ComputerSet_SlaveAlreadyExists | Node already exists | ノード名重複時 | エラー |
| Slave_InvalidConfig_Executors | Invalid number of executors for {0} | エグゼキュータ数が無効時 | エラー |
| FormValidation.ok | (空または成功メッセージ) | バリデーション成功時 | 成功 |

## 例外処理

| 例外条件 | 対応処理 |
|---------|---------|
| 権限不足（EXTENDED_READ以下） | アクセス拒否（403） |
| ノードが存在しない | 404エラー |
| ノード名重複 | FormExceptionでエラーメッセージ表示 |
| エグゼキュータ数が0以下 | FormExceptionでエラーメッセージ表示 |
| バリデーションエラー | 該当項目にエラーメッセージを表示 |

## 備考

- Computer.EXTENDED_READ権限のみの場合、読み取り専用モードで表示される
- ノード名を変更した場合、設定ディレクトリがリネームされる
- 起動方法と可用性の設定は拡張ポイントであり、プラグインにより選択肢が追加される
- ビルトインノード（コントローラー）の設定はシステム設定画面で行う

---

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

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

### 推奨読解順序

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

まず、ノード設定に関連するデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Slave.java | `core/src/main/java/hudson/model/Slave.java` | エージェントノードの設定を保持するクラス |
| 1-2 | Node.java | `core/src/main/java/hudson/model/Node.java` | ノードの基底クラス、共通設定項目 |
| 1-3 | ComputerLauncher.java | `core/src/main/java/hudson/slaves/ComputerLauncher.java` | 起動方法の基底クラス |
| 1-4 | RetentionStrategy.java | `core/src/main/java/hudson/slaves/RetentionStrategy.java` | 可用性戦略の基底クラス |

**読解のコツ**: SlaveクラスはNodeを継承し、エージェントノード固有の設定（remoteFS, launcher等）を追加している。

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

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | configure.jelly | `core/src/main/resources/hudson/model/Computer/configure.jelly` | 画面のビューテンプレート |
| 2-2 | configure-entries.jelly | `core/src/main/resources/hudson/model/Slave/configure-entries.jelly` | ノードタイプ別の設定項目 |

**主要処理フロー**:
1. **行31**: レイアウト開始、EXTENDED_READ権限チェック
2. **行32**: readOnlyMode判定（CONFIGURE権限がない場合は読み取り専用）
3. **行36-50**: フォームの構築、configSubmitアクションへPOST
4. **行41-43**: ノード名入力フィールド
5. **行47**: configure-entries.jellyのインクルード（ノードタイプ別設定）
6. **行49**: Save/Applyボタンバー

#### Step 3: 設定保存処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Computer.java | `core/src/main/java/hudson/model/Computer.java` | doConfigSubmit()メソッド（行1484-1518）で設定保存 |
| 3-2 | Nodes.java | `core/src/main/java/jenkins/model/Nodes.java` | replaceNode()メソッドでノード置換 |

**主要処理フロー**:
- **行1484-1518**: doConfigSubmit()がフォームを受け取り、バリデーション後にNode.reconfigure()を呼び出し
- **行1488-1489**: ノード名のバリデーション
- **行1496-1498**: 名前重複チェック
- **行1501-1503**: エグゼキュータ数バリデーション
- **行1506**: Node.reconfigure()で設定更新
- **行1507**: Jenkins.getNodesObject().replaceNode()でノード置換

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

```
HTTP Request: GET /computer/{nodeName}/configure
    │
    ├─ Computer (Model Object)
    │      ├─ getNode() → Node (設定情報)
    │      └─ hasPermission(CONFIGURE) → readOnlyMode判定
    │
    └─ configure.jelly (View)
           ├─ f:form → configSubmitへPOST
           ├─ f:entry (name) → ノード名入力
           └─ st:include configure-entries.jelly
                  ├─ f:entry (numExecutors)
                  ├─ f:entry (remoteFS)
                  ├─ f:entry (labelString)
                  ├─ f:entry (mode)
                  ├─ f:dropdownDescriptorSelector (launcher)
                  ├─ f:dropdownDescriptorSelector (retentionStrategy)
                  └─ f:descriptorList (nodeProperties)

HTTP Request: POST /computer/{nodeName}/configSubmit
    │
    └─ Computer.doConfigSubmit()
           ├─ checkPermission(CONFIGURE)
           ├─ Jenkins.checkGoodName(proposedName)
           ├─ getSubmittedForm()
           ├─ Node.reconfigure(req, form)
           └─ Jenkins.getNodesObject().replaceNode(old, new)
                  └─ save() → config.xml更新
```

### データフロー図

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

フォーム入力値       Computer                 config.xml
name, executors ───▶ doConfigSubmit() ───▶ nodes/{name}/config.xml
launcher, etc.           │
                         ▼
                    Node.reconfigure()
                         │
                         ▼
                    Nodes.replaceNode()
                         │
                         ▼
                    config.xml保存
                         │
                         ▼
                    リダイレクト ───▶ ノード詳細画面
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| configure.jelly | `core/src/main/resources/hudson/model/Computer/configure.jelly` | テンプレート | 設定画面のベーステンプレート |
| configure-entries.jelly | `core/src/main/resources/hudson/model/Slave/configure-entries.jelly` | テンプレート | Slave固有の設定項目 |
| Computer.java | `core/src/main/java/hudson/model/Computer.java` | ソース | doConfigSubmit()による設定保存 |
| Slave.java | `core/src/main/java/hudson/model/Slave.java` | ソース | エージェントノード設定クラス |
| Node.java | `core/src/main/java/hudson/model/Node.java` | ソース | ノード基底クラス |
| ComputerLauncher.java | `core/src/main/java/hudson/slaves/ComputerLauncher.java` | ソース | 起動方法基底クラス |
| RetentionStrategy.java | `core/src/main/java/hudson/slaves/RetentionStrategy.java` | ソース | 可用性戦略基底クラス |
| Nodes.java | `core/src/main/java/jenkins/model/Nodes.java` | ソース | ノード管理クラス |
