# 機能設計書 68-ラベル管理

## 概要

本ドキュメントは、Jenkins におけるノード/エージェントのラベル管理機能の設計について記述する。

### 本機能の処理概要

ラベル管理機能は、Jenkins のノード（エージェント）をグループ化し、ジョブの実行場所を制御するための基盤機能である。ラベル式による複雑な条件指定も可能。

**業務上の目的・背景**：大規模な CI/CD 環境では、異なる特性を持つ多数のエージェント（OS、アーキテクチャ、インストール済みツールなど）が存在する。ラベル管理機能は、ジョブを適切なエージェントで実行するためのマッチング機能を提供する。これにより、Linux 専用のビルド、GPU を持つノードでの機械学習タスク、特定のツールがインストールされたノードでのテストなど、柔軟な実行環境の指定が可能になる。

**機能の利用シーン**：
- ジョブの実行ノード指定
- パイプラインの agent 指定
- ノードのグループ化と管理
- Cloud による動的エージェントプロビジョニング
- 負荷分散のための Executor 配分

**主要な処理内容**：
1. ラベル式の解析（ANTLR パーサー使用）
2. ノードとラベルのマッチング
3. ラベルアトム（単一ラベル）と式（複合ラベル）の管理
4. ラベルごとの統計情報（Executor 数、ビジー状態等）の計算
5. Cloud によるラベル対応ノードのプロビジョニング
6. ジョブとラベルの関連付け管理

**関連システム・外部連携**：
- Node: エージェントノード
- Cloud: 動的エージェントプロビジョニング
- Queue: ジョブキューイング
- LoadStatistics: 負荷統計
- NodeProvisioner: ノード動的追加

**権限による制御**：ラベル管理自体には特別な権限制御はないが、ノード設定にはノード管理権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 22 | ノード一覧 | 参照画面 | ノードのラベル表示 |
| 23 | ノード設定 | 参照画面 | ノードのラベル設定 |
| 12 | ジョブ設定 | 参照画面 | ジョブの実行ラベル指定 |

## 機能種別

リソース管理 / スケジューリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| labelExpression | String | No | ラベル式（例: "linux && jdk11"） | 有効なラベル式構文 |
| labelName | String | No | 単一ラベル名 | 空白を含まない文字列 |

### 入力データソース

- ジョブ設定
- ノード設定
- Pipeline の agent 指定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Label | Label | ラベルオブジェクト |
| nodes | Set<Node> | ラベルに属するノード |
| clouds | Set<Cloud> | ラベル対応の Cloud |
| executors | int | Executor 数統計 |

### 出力先

- Queue: ジョブスケジューリング
- UI: ラベル情報表示

## 処理フロー

### 処理シーケンス

```
1. ラベル式の解析
   └─ parseExpression() で文字列を Label オブジェクトに変換
   └─ ANTLR パーサーで構文解析

2. ラベルの取得
   └─ Jenkins.getLabel() でラベルを取得または作成

3. ノードマッチング
   └─ Label.matches(Node) でノードがラベルに属するか判定

4. 統計情報の計算
   └─ getTotalExecutors(), getBusyExecutors(), getIdleExecutors()

5. Cloud 対応確認
   └─ Cloud.canProvision() でプロビジョニング可能か確認

6. キャッシュのリセット（必要時）
   └─ reset() でノード/Cloud キャッシュをクリア
```

### フローチャート

```mermaid
flowchart TD
    A[ラベル式入力] --> B[parseExpression]
    B --> C{式の種類}
    C -->|単一| D[LabelAtom]
    C -->|AND| E[LabelExpression.And]
    C -->|OR| F[LabelExpression.Or]
    C -->|NOT| G[LabelExpression.Not]
    D --> H[matches評価]
    E --> H
    F --> H
    G --> H
    H --> I{ノード取得}
    I --> J[getNodes]
    J --> K[統計計算]
    K --> L{Cloud対応?}
    L -->|Yes| M[プロビジョニング可能]
    L -->|No| N[既存ノードのみ]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-68-01 | ラベル式構文 | &&（AND）、\|\|（OR）、!（NOT）、()（グルーピング）をサポート | ラベル式解析時 |
| BR-68-02 | 大文字小文字区別 | ラベル名は大文字小文字を区別する | 常時 |
| BR-68-03 | セルフラベル | ノード名は自動的にそのノードのラベルとなる | 常時 |
| BR-68-04 | 空ラベル | ラベルなしジョブはどのノードでも実行可能 | ジョブにラベル指定なし |
| BR-68-05 | Cloud プロビジョニング | ラベルに対応する Cloud がある場合、必要に応じてノードを動的追加 | Cloud 設定時 |

### 計算ロジック

**ラベル式の評価**:
- LabelAtom: ノードが当該ラベルを持つか直接チェック
- And: 左辺と右辺の両方が true の場合 true
- Or: 左辺または右辺のいずれかが true の場合 true
- Not: 評価結果を反転
- Iff: 双条件（同値）
- Implies: 含意

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

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

該当なし（ラベル管理はメモリ上で動作、設定は XML ファイルに永続化）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IllegalArgumentException | 構文エラー | ラベル式の構文が不正 | エラーメッセージを表示 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- ラベル評価は高頻度で行われるため高速である必要がある
- ノード/Cloud キャッシュによる効率化
- トポロジカルな変更時のみキャッシュをリセット

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

- ラベル式のパースは ANTLR で安全に行われる
- ノード操作には適切な権限が必要

## 備考

- Label は抽象クラスで、LabelAtom と LabelExpression の派生クラスがある
- LabelExpression には And, Or, Not, Iff, Implies, Paren のサブクラスがある
- XStream の Converter でラベルのシリアライズに対応

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Label.java | `core/src/main/java/hudson/model/Label.java` | Label 抽象クラスの構造（92-125行目） |

**読解のコツ**: Label は抽象クラスで、name、nodes、clouds、loadStatistics、nodeProvisioner をフィールドとして持つ。getNodes() と getClouds() でキャッシュを使用している点に注目。

#### Step 2: ラベル式の解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Label.java | `core/src/main/java/hudson/model/Label.java` | parseExpression() メソッド（621-629行目） |

**主要処理フロー**:
1. **622行目**: ANTLR Lexer の生成
2. **623-624行目**: エラーリスナーの設定
3. **625-627行目**: ANTLR Parser の生成とエラーリスナー設定
4. **628行目**: expr().l でパース結果を取得

#### Step 3: マッチング処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Label.java | `core/src/main/java/hudson/model/Label.java` | matches() メソッド（172-191行目） |

**主要処理フロー**:
- **172行目**: matches(VariableResolver) - 抽象メソッド
- **178-188行目**: matches(Collection<LabelAtom>) - ラベルコレクションとのマッチング
- **190-192行目**: matches(Node) - ノードとのマッチング

#### Step 4: 統計情報を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Label.java | `core/src/main/java/hudson/model/Label.java` | getTotalExecutors() 等（303-339行目） |

**主要処理フロー**:
- **303-311行目**: getTotalExecutors() - 全 Executor 数
- **317-325行目**: getBusyExecutors() - ビジー Executor 数
- **331-339行目**: getIdleExecutors() - アイドル Executor 数

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

```
Label 操作
    │
    ├─ parseExpression(labelExpression)
    │      ├─ LabelExpressionLexer 生成 (622行目)
    │      ├─ LabelExpressionParser 生成 (625行目)
    │      └─ parser.expr().l (628行目)
    │
    ├─ matches(node)
    │      └─ matches(node.getAssignedLabels()) (191行目)
    │             └─ matches(VariableResolver) - 抽象メソッド
    │
    ├─ getNodes()
    │      ├─ キャッシュチェック (208-209行目)
    │      └─ Jenkins.get() からノード収集 (211-219行目)
    │
    └─ getClouds()
           ├─ キャッシュチェック (253行目)
           └─ cloud.canProvision() チェック (256-258行目)
```

### データフロー図

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

ラベル式文字列 ─────▶ parseExpression()
                              │
                              ▼
                       ANTLR パーサー ──────────▶ Label オブジェクト
                              │
                              ▼
ノード設定 ────────▶ matches(node) ──────────▶ boolean
                              │
                              ▼
                       getNodes() ─────────────▶ Set<Node>
                              │
                              ▼
Cloud 設定 ────────▶ getClouds() ─────────────▶ Set<Cloud>
                              │
                              ▼
                       getTotalExecutors() ────▶ 統計情報
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Label.java | `core/src/main/java/hudson/model/Label.java` | ソース | ラベル管理の主要クラス |
| LabelAtom.java | `core/src/main/java/hudson/model/labels/LabelAtom.java` | ソース | 単一ラベル |
| LabelExpression.java | `core/src/main/java/hudson/model/labels/LabelExpression.java` | ソース | 複合ラベル式 |
| LabelExpressionLexer.java | `core/target/.../LabelExpressionLexer.java` | 生成ソース | ANTLR Lexer |
| LabelExpressionParser.java | `core/target/.../LabelExpressionParser.java` | 生成ソース | ANTLR Parser |
| Node.java | `core/src/main/java/hudson/model/Node.java` | ソース | ノード基底クラス |
| Cloud.java | `core/src/main/java/hudson/slaves/Cloud.java` | ソース | Cloud プロバイダー |
| LoadStatistics.java | `core/src/main/java/hudson/model/LoadStatistics.java` | ソース | 負荷統計 |
