# 帳票設計書 12-Plugins Report

## 概要

本ドキュメントは、OpenSearchのCat API「/_cat/plugins」エンドポイントが出力するPlugins Reportの設計仕様を定義する。本帳票はクラスタ内の各ノードにインストールされたプラグインの情報（名前・バージョン・説明）をテキストテーブル形式にて出力するものである。

### 本帳票の処理概要

本帳票は、OpenSearchクラスタの全ノードにおけるプラグインのインストール状況を一覧化する。クラスタステートからノード一覧を取得し、続いてノード情報APIからプラグイン情報を取得する2段階の非同期処理で構成される。

**業務上の目的・背景**：OpenSearchクラスタでは各ノードに異なるプラグインがインストールされている可能性があり、プラグインのバージョン不一致はクラスタの不安定化を招く。本帳票によりクラスタ全体のプラグイン構成を一目で把握し、不整合を検出できる。

**帳票の利用シーン**：クラスタ構成の確認、プラグインアップグレード前後のバージョン確認、新ノード追加後のプラグイン整合性チェック、セキュリティ監査におけるインストール済みプラグインの棚卸しに利用される。

**主要な出力内容**：
1. ノード識別情報（ノードID、ノード名）
2. プラグインコンポーネント名
3. プラグインバージョン
4. プラグイン説明文

**帳票の出力タイミング**：ユーザーがREST APIエンドポイント `GET /_cat/plugins` にHTTPリクエストを送信した際にリアルタイムで生成・出力される。

**帳票の利用者**：OpenSearchクラスタ管理者、セキュリティ監査担当者、運用チーム。

## 帳票種別

一覧表（ノード別プラグイン一覧）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | REST API | `GET /_cat/plugins` | HTTPリクエスト送信 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | text/plain（テキストテーブル）またはJSON/YAML（format指定時） |
| 用紙サイズ | N/A（API応答） |
| 向き | N/A |
| ファイル名 | N/A（HTTPレスポンスボディ） |
| 出力方法 | HTTPレスポンス |
| 文字コード | UTF-8 |

### PDF固有設定

該当なし

### Excel固有設定

該当なし

## 帳票レイアウト

### レイアウト概要

テキストテーブル形式で、1行が1ノードの1プラグインに対応する一覧を出力する。

```
┌──────────────────────────────────────────────────────┐
│  ヘッダー部（カラム名: name, component, version,      │
│             description※デフォルト非表示）             │
├──────────────────────────────────────────────────────┤
│  明細部（ノード×プラグインごとに1行）                    │
│  例: node1  analysis-icu  2.x.x                      │
│      node1  repository-s3 2.x.x                      │
│      node2  analysis-icu  2.x.x                      │
└──────────────────────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | id | ノードID（デフォルト非表示） | DiscoveryNode.getId() | 文字列 |
| 2 | name | ノード名 | DiscoveryNode.getName() | 文字列（alias: n） |
| 3 | component | プラグイン名 | PluginInfo.getName() | 文字列（alias: c） |
| 4 | version | プラグインバージョン | PluginInfo.getVersion() | 文字列（alias: v） |
| 5 | description | プラグイン説明（デフォルト非表示） | PluginInfo.getDescription() | 文字列（alias: d） |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | id | ノードID | DiscoveryNode.getId() | 文字列 | 可変 |
| 2 | name | ノード名 | DiscoveryNode.getName() | 文字列 | 可変 |
| 3 | component | プラグイン名 | PluginInfo.getName() | 文字列 | 可変 |
| 4 | version | プラグインバージョン | PluginInfo.getVersion() | 文字列 | 可変 |
| 5 | description | プラグイン説明 | PluginInfo.getDescription() | 文字列 | 可変 |

### フッター部

フッター部は存在しない。

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| local | ローカルノードのクラスタステートのみ参照するか | No（デフォルト: false） |
| cluster_manager_timeout | クラスタマネージャノードへのタイムアウト | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | ノード順 | DiscoveryNodesのイテレーション順 |
| 2 | プラグイン順 | PluginInfosのリスト順 |

### 改ページ条件

改ページなし。

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| ClusterState.nodes（内部API） | ノード一覧取得 | ClusterStateRequest.clear().nodes(true) |
| NodesInfo.PLUGINS（内部API） | プラグイン情報取得 | NodesInfoRequest.clear().addMetric(PLUGINS) |

### テーブル別参照項目詳細

#### ClusterStateResponse

| 参照項目 | 帳票項目との対応 | 取得条件 | 備考 |
|---------|----------------|---------|------|
| DiscoveryNode.getId() | id | - | ノードID |
| DiscoveryNode.getName() | name | - | ノード名 |

#### NodesInfoResponse

| 参照項目 | 帳票項目との対応 | 取得条件 | 備考 |
|---------|----------------|---------|------|
| PluginInfo.getName() | component | NodeInfo.getInfo(PluginsAndModules.class).getPluginInfos() | プラグイン名 |
| PluginInfo.getVersion() | version | 同上 | バージョン |
| PluginInfo.getDescription() | description | 同上 | 説明文 |

## 計算仕様

### 計算項目一覧

本帳票に計算項目は存在しない。

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[クライアントからGETリクエスト受信] --> B[RestPluginsAction.doCatRequest]
    B --> C[ClusterStateRequest生成 - nodes=true]
    C --> D[NodeClient.admin.cluster.state実行]
    D --> E[ClusterStateResponse受信]
    E --> F[NodesInfoRequest生成 - PLUGINS指定]
    F --> G[NodeClient.admin.cluster.nodesInfo実行]
    G --> H[NodesInfoResponse受信]
    H --> I[buildTable: DiscoveryNodesをループ]
    I --> J[各ノードのPluginInfosをループ]
    J --> K[テーブル行追加]
    K --> L[RestTable.buildResponse]
    L --> M[HTTPレスポンス返却]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| ノード情報なし | NodesInfoResponseにノードのエントリがない場合 | 行をスキップ（行126-128: info==null時continue） | ノード離脱を想定した安全なスキップ処理 |
| プラグイン情報なし | PluginsAndModulesがnullの場合 | 行をスキップ（行130-132: plugins==null時continue） | プラグイン未インストールノード対応 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | ノード数 x プラグイン数（典型的には数十行） |
| 目標出力時間 | クラスタステート取得 + ノード情報取得（通常1秒以内） |
| 同時出力数上限 | REST APIスレッドプールに依存 |

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

プラグイン一覧はクラスタの構成情報を公開するため、cluster:monitor/state および cluster:monitor/nodes/info 権限を持つユーザーのみアクセス可能とすべきである。

## 備考

- 2段階の非同期処理（ClusterState取得 -> NodesInfo取得）で構成される
- `?v` パラメータでヘッダー行表示
- `?h=name,component,version` でカラム指定可能
- id と description はデフォルト非表示（`default:false`）
- `master_timeout` パラメータは非推奨（deprecation警告あり）。`cluster_manager_timeout` を使用すべき

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | PluginInfo.java | `server/src/main/java/org/opensearch/plugins/PluginInfo.java` | プラグインメタ情報のデータ構造（name, version, description） |
| 1-2 | PluginsAndModules.java | `server/src/main/java/org/opensearch/action/admin/cluster/node/info/PluginsAndModules.java` | プラグインとモジュールを保持するコンテナ |
| 1-3 | NodeInfo.java | `server/src/main/java/org/opensearch/action/admin/cluster/node/info/NodeInfo.java` | getInfo(PluginsAndModules.class)でプラグイン情報を取得 |

**読解のコツ**: PluginsAndModulesはNodeInfoのgetInfo()メソッドでクラスを指定して取得するジェネリックな構造である。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestPluginsAction.java | `server/src/main/java/org/opensearch/rest/action/cat/RestPluginsAction.java` | 帳票メインクラス。146行 |

**主要処理フロー**:
1. **行67-69**: routes()で `/_cat/plugins` ルートを定義
2. **行82-105**: doCatRequest()で2段階非同期処理を実装
3. **行83-84**: ClusterStateRequest で nodes=true 指定
4. **行91-104**: RestActionListenerでClusterState受信後、NodesInfoRequest を発行
5. **行94-96**: NodesInfoRequest で PLUGINS メトリック指定
6. **行108-118**: getTableWithHeader()で5カラム定義（id はデフォルト非表示）
7. **行120-145**: buildTable()でノード×プラグインのループ

#### Step 3: 基底クラスと出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AbstractCatAction.java | `server/src/main/java/org/opensearch/rest/action/cat/AbstractCatAction.java` | help/format パラメータ処理 |
| 3-2 | RestTable.java | `server/src/main/java/org/opensearch/rest/action/cat/RestTable.java` | 最終的なテキスト/JSON出力 |

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

```
HTTP GET /_cat/plugins
    |
    +-- AbstractCatAction.prepareRequest() [行68]
        |
        +-- RestPluginsAction.doCatRequest() [行82]
            |
            +-- ClusterStateRequest.clear().nodes(true) [行83-84]
            +-- NodeClient.admin().cluster().state() [行91]
                |
                +-- RestActionListener.processResponse() [行93]
                    |
                    +-- NodesInfoRequest.addMetric(PLUGINS) [行96]
                    +-- NodeClient.admin().cluster().nodesInfo() [行97]
                        |
                        +-- RestResponseListener.buildResponse() [行99]
                            |
                            +-- buildTable() [行120]
                            |   +-- DiscoveryNodes loop [行124]
                            |       +-- NodesInfoResponse lookup [行125]
                            |       +-- PluginInfos loop [行133]
                            |           +-- table.addCell() x 5 [行135-139]
                            |
                            +-- RestTable.buildResponse() [行100]
```

### データフロー図

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

HTTP GET Request   --> RestPluginsAction                --> HTTP Response
  /_cat/plugins         |                                   (text/plain
                        +-> ClusterStateRequest              or JSON)
                        |   (nodes only)
                        +-> ClusterStateResponse
                        |   (DiscoveryNodes)
                        +-> NodesInfoRequest
                        |   (PLUGINS metric)
                        +-> NodesInfoResponse
                        |   (NodeInfo[] with PluginInfos)
                        +-> buildTable()
                        |   (Table object)
                        +-> RestTable.buildResponse()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RestPluginsAction.java | `server/src/main/java/org/opensearch/rest/action/cat/RestPluginsAction.java` | ソース | 帳票メインクラス（146行） |
| AbstractCatAction.java | `server/src/main/java/org/opensearch/rest/action/cat/AbstractCatAction.java` | ソース | Cat API基底クラス |
| RestTable.java | `server/src/main/java/org/opensearch/rest/action/cat/RestTable.java` | ソース | テーブルレスポンス構築 |
| PluginInfo.java | `server/src/main/java/org/opensearch/plugins/PluginInfo.java` | ソース | プラグインメタ情報 |
| PluginsAndModules.java | `server/src/main/java/org/opensearch/action/admin/cluster/node/info/PluginsAndModules.java` | ソース | プラグイン/モジュールコンテナ |
| NodeInfo.java | `server/src/main/java/org/opensearch/action/admin/cluster/node/info/NodeInfo.java` | ソース | ノード情報 |
| NodesInfoRequest.java | `server/src/main/java/org/opensearch/action/admin/cluster/node/info/NodesInfoRequest.java` | ソース | ノード情報リクエスト |
| ClusterStateRequest.java | `server/src/main/java/org/opensearch/action/admin/cluster/state/ClusterStateRequest.java` | ソース | クラスタステートリクエスト |
| ActionModule.java | `server/src/main/java/org/opensearch/action/ActionModule.java` | ソース | アクション登録 |
