# 機能設計書 44-Groovyコンソール

## 概要

本ドキュメントは、JenkinsのGroovyスクリプト実行機能（Groovyコンソール）の機能設計を記載する。CLIコマンド（groovy/groovysh）とWeb UI（スクリプトコンソール）の両方から利用可能。

### 本機能の処理概要

GroovyコンソールはJenkinsサーバー上でGroovyスクリプトを実行するための機能を提供する。管理者がJenkinsの内部オブジェクトに直接アクセスし、一括操作やトラブルシューティング、設定変更を行うことができる。

**業務上の目的・背景**：大規模なJenkins環境では、Web UIでは不可能または非効率な一括操作が必要になることがある。Groovyコンソールを使用することで、Jenkinsの内部APIに直接アクセスし、柔軟なスクリプト処理を実行できる。また、トラブルシューティングやデバッグにも有用である。

**機能の利用シーン**：
- 大量のジョブ設定を一括変更
- ビルド履歴の一括削除やクリーンアップ
- プラグイン設定の確認・変更
- Jenkinsの内部状態の診断
- セキュリティ設定の緊急変更

**主要な処理内容**：
1. `groovy`: 標準入力またはファイルからGroovyスクリプトを読み込んで実行
2. `groovysh`: インタラクティブなGroovyシェルを起動
3. Web UI: スクリプトコンソール画面からスクリプトを入力・実行

**関連システム・外部連携**：Jenkinsの全ての内部オブジェクト（jenkins, jobs, nodes, plugins等）にアクセス可能。

**権限による制御**：Jenkins.ADMINISTER権限が必須。スクリプト実行はJVMの状態を操作可能なため、最高レベルの権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 60 | スクリプトコンソール | 主画面 | Groovyスクリプトの実行 |

## 機能種別

スクリプト実行 / 管理ツール

## 入力仕様

### 入力パラメータ

#### groovy コマンド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| script | String | Yes | スクリプトソース（「=」で標準入力） | 有効なGroovy構文 |
| ARGUMENTS | List<String> | No | スクリプトに渡すコマンドライン引数 | - |

#### groovysh コマンド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ARGS | List<String> | No | Groovyシェルに渡す引数 | - |

### 入力データソース

- CLI経由でのコマンドライン引数
- 標準入力（groovyコマンドで「=」指定時）
- Web UIからのフォーム入力

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| stdout | Object | スクリプト実行結果（printlnの出力や戻り値） |
| stderr | String | エラーメッセージ |
| returnCode | int | 0=成功、非0=エラー |

### 出力先

- 標準出力（スクリプト実行結果）
- 標準エラー出力（エラーメッセージ）
- Web UI（スクリプトコンソール画面に結果表示）

## 処理フロー

### 処理シーケンス

#### groovy コマンド

```
1. 権限チェック
   └─ Jenkins.ADMINISTER権限を確認
2. スクリプト読み込み
   └─ 引数が「=」の場合は標準入力から読み込み
3. Binding設定
   └─ out, stdin, stdout, stderrをバインド
4. GroovyShell生成
   └─ PluginManager.uberClassLoaderを使用
5. スクリプト実行
   └─ groovy.run(script, "RemoteClass", arguments)
6. ScriptListener通知
   └─ スクリプト実行をセキュリティログに記録
```

#### groovysh コマンド

```
1. 権限チェック
   └─ Jenkins.ADMINISTER権限を確認
2. ターミナル設定
   └─ UnsupportedTerminalを使用（リモート環境用）
3. Binding設定
   └─ out, hudson, jenkinsをバインド
4. Groovyshシェル生成
   └─ IO設定とカスタムコマンド登録
5. インタラクティブ実行
   └─ shell.run()でREPLループ開始
6. 入力ログ記録
   └─ 各行の入力をScriptListenerで記録
```

### フローチャート

```mermaid
flowchart TD
    A[コマンド/Web受信] --> B[権限チェック]
    B -->|権限あり| C{実行モード}
    B -->|権限なし| D[エラー: 権限不足]

    C -->|groovy| E[スクリプト読み込み]
    E --> F[Binding設定]
    F --> G[GroovyShell生成]
    G --> H[スクリプト実行]
    H --> I[ScriptListener通知]
    I --> J[結果出力]
    J --> K[return 0]

    C -->|groovysh| L[ターミナル設定]
    L --> M[Binding設定]
    M --> N[Groovyshシェル生成]
    N --> O[REPLループ開始]
    O --> P{入力あり?}
    P -->|Yes| Q[スクリプト実行]
    Q --> R[結果表示]
    R --> S[ScriptListener通知]
    S --> P
    P -->|終了| K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-44-01 | 管理者権限必須 | スクリプト実行にはJenkins.ADMINISTER権限が必須 | 全操作 |
| BR-44-02 | プラグインクラスアクセス | PluginManager.uberClassLoaderによりプラグインのクラスにもアクセス可能 | 全操作 |
| BR-44-03 | スクリプトログ記録 | 全てのスクリプト実行はScriptListenerで記録される | 全操作 |
| BR-44-04 | 標準入力制限 | groovyコマンドは「=」のみをスクリプトソースとしてサポート | groovyコマンド |
| BR-44-05 | Jenkinsオブジェクトバインド | groovyshではjenkins/hudsonオブジェクトが事前にバインドされる | groovyshコマンド |

### 計算ロジック

該当なし

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

Groovyスクリプトから直接Jenkinsの内部状態を操作可能。操作内容はスクリプト次第。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| AccessDeniedException | 権限不足 | Jenkins.ADMINISTER権限がない | 管理者に権限付与を依頼 |
| CmdLineException | スクリプト未指定 | groovyコマンドでスクリプトが指定されない | スクリプトを指定 |
| GroovyRuntimeException | 構文エラー | Groovyスクリプトに構文エラー | スクリプトを修正 |
| Exception | 実行時エラー | スクリプト実行中にエラー発生 | エラーメッセージを確認 |

### リトライ仕様

スクリプト実行はアトミックではないため、途中で失敗した場合は状態を確認してから再実行する必要がある。

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

Groovyスクリプト実行にはトランザクション制御がない。スクリプト内で複数の操作を行う場合、途中でエラーが発生すると一部のみが適用された状態になる可能性がある。

## パフォーマンス要件

- スクリプト起動オーバーヘッド: 1秒以内
- 実行時間: スクリプト内容に依存

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

- **最高権限要求**: JVMの状態を操作可能なため、Jenkins.ADMINISTER権限が必須
- **監査ログ**: ScriptListenerにより全てのスクリプト実行がログに記録される
- **セキュリティリスク**: 悪意のあるスクリプトはシステム全体に影響を与える可能性がある
- **認証情報アクセス**: Credentialsプラグイン等の機密情報にアクセス可能

## 備考

- groovyshでは`hudson.model.*`がデフォルトでインポートされる
- commands.xmlでカスタムコマンドを登録可能
- Web UIのスクリプトコンソールからも同等の機能を利用可能

---

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

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

### 推奨読解順序

#### Step 1: Groovyコマンドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | GroovyCommand.java | `core/src/main/java/hudson/cli/GroovyCommand.java` | 単発スクリプト実行の実装 |
| 1-2 | GroovyshCommand.java | `core/src/main/java/hudson/cli/GroovyshCommand.java` | インタラクティブシェルの実装 |

**主要処理フロー（GroovyCommand）**:
- **65-66行目**: 権限チェック（Jenkins.ADMINISTER）
- **70-74行目**: Binding設定（out, stdin, stdout, stderr）
- **76行目**: GroovyShell生成（uberClassLoader使用）
- **77-78行目**: ScriptListener通知とスクリプト実行
- **86-93行目**: スクリプト読み込み処理（「=」のみサポート）

**主要処理フロー（GroovyshCommand）**:
- **71-72行目**: 権限チェック
- **75-76行目**: UnsupportedTerminal設定（リモート用）
- **107-109行目**: jenkins/hudsonオブジェクトのバインド
- **111-113行目**: IO設定（ScriptListener連携）
- **132-133行目**: Groovyshシェル生成とhudson.model.*インポート
- **145-148行目**: 入力ログ記録（maybeRecordInput）

#### Step 2: セキュリティログ機構を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ScriptListener.java | `core/src/main/java/jenkins/util/ScriptListener.java` | スクリプト実行の監査ログ機構 |

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

```
CLI Client / Web UI
    │
    ├─ GroovyCommand
    │      ├─ Jenkins.checkPermission(ADMINISTER)
    │      ├─ loadScript() - スクリプト読み込み
    │      ├─ Binding設定
    │      │      ├─ out → PrintWriter(ScriptListener.ListenerWriter)
    │      │      ├─ stdin → InputStream
    │      │      ├─ stdout → PrintStream
    │      │      └─ stderr → PrintStream
    │      ├─ GroovyShell生成
    │      │      └─ ClassLoader: PluginManager.uberClassLoader
    │      ├─ ScriptListener.fireScriptExecution() - 実行前通知
    │      └─ groovy.run() - スクリプト実行
    │
    └─ GroovyshCommand
           ├─ Jenkins.checkPermission(ADMINISTER)
           ├─ TerminalFactory.reset() - ターミナル設定
           ├─ Binding設定
           │      ├─ out → PrintWriter(ScriptListener.ListenerOutputStream)
           │      ├─ hudson → Jenkins.get()
           │      └─ jenkins → Jenkins.get()
           ├─ IO設定
           │      └─ ScriptListener.ListenerOutputStream連携
           ├─ LoggingGroovySh生成
           │      └─ maybeRecordInput() - 入力ログ
           └─ shell.run() - REPLループ
```

### データフロー図

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

標準入力 (スクリプト) ───▶ GroovyCommand ─────────────────────▶ 標準出力 (結果)
                              │
                              ├─ ScriptListener.fireScriptExecution()
                              │
                              └─ GroovyShell.run()
                                     │
                                     ├─ Jenkins内部オブジェクト参照/操作
                                     │      ├─ jenkins.getItems()
                                     │      ├─ jenkins.getNodes()
                                     │      └─ ... (任意のAPI)
                                     │
                                     └─ 結果出力
                                            ├─ println → stdout
                                            └─ 戻り値 → stdout
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| GroovyCommand.java | `core/src/main/java/hudson/cli/GroovyCommand.java` | ソース | 単発スクリプト実行コマンド |
| GroovyshCommand.java | `core/src/main/java/hudson/cli/GroovyshCommand.java` | ソース | インタラクティブシェルコマンド |
| ScriptListener.java | `core/src/main/java/jenkins/util/ScriptListener.java` | ソース | スクリプト実行監査ログ |
| commands.xml | `core/src/main/resources/hudson/cli/commands.xml` | 設定 | カスタムコマンド定義 |
