# 画面設計書 89-Terraform状態一覧

## 概要

本ドキュメントは、GitLabのTerraform状態一覧画面の設計仕様を定義するものである。

### 本画面の処理概要

Terraform状態一覧画面は、プロジェクトに保存されているTerraform状態ファイル（tfstate）を一覧表示し、管理するための画面である。GitLabをTerraformのバックエンドとして使用する際に、状態ファイルの確認、バージョン管理、ロック状態の確認が可能。

**業務上の目的・背景**：Infrastructure as Code（IaC）の実践において、Terraformの状態ファイルはインフラの現在状態を記録する重要なファイルである。チーム開発では状態ファイルの共有と競合防止が必要であり、GitLabがHTTPバックエンドとして状態ファイルを管理することで、バージョン管理、ロック機能、アクセス制御を一元化できる。

**画面へのアクセス方法**：プロジェクトのサイドメニューから「Operate」>「Terraform states」を選択、またはURL直接アクセス。URLパターンは `/:namespace/:project/-/terraform` となる。

**主要な操作・処理内容**：
1. Terraform状態の一覧表示
2. 状態のロック/アンロック確認
3. 状態の削除
4. バージョン履歴の確認
5. API設定情報の表示

**画面遷移**：
- 遷移元：プロジェクトサイドメニュー
- 遷移先：特になし（モーダル表示で操作）

**権限による表示制御**：
- `read_terraform_state`権限がない場合はアクセス不可
- `admin_terraform_state`権限を持つユーザーのみ削除・アンロック操作が可能

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | Terraform状態管理 | 主機能 | Terraform状態の一覧表示・管理 |

## 画面種別

一覧

## URL/ルーティング

```
GET /:namespace/:project/-/terraform
POST /api/graphql (GraphQL Query: terraformStates)
DELETE /api/v4/projects/:id/terraform/state/:name (REST API)
POST /api/v4/projects/:id/terraform/state/:name/lock (REST API)
DELETE /api/v4/projects/:id/terraform/state/:name/lock (REST API)
```

## 入出力項目

### フィルタ/ソート項目

| 項目名 | データ型 | 必須 | 説明 |
|--------|----------|------|------|
| sort | String | - | ソート順 |
| before | String | - | カーソルベースページネーション（前ページ） |
| after | String | - | カーソルベースページネーション（次ページ） |

## 表示項目

### Terraform状態カード

| 項目名 | データ型 | 説明 | ソース |
|--------|----------|------|--------|
| 状態名 | String | Terraform状態の名前 | terraformState.name |
| ロック状態 | Boolean | ロック中かどうか | terraformState.locked |
| ロックユーザー | User | ロックしているユーザー | terraformState.lockedByUser |
| 最終更新日時 | DateTime | 最終更新日時 | terraformState.updatedAt |
| バージョン数 | Integer | バージョンの総数 | terraformState.versionsCount |
| 最新バージョン | Object | 最新バージョン情報 | terraformState.latestVersion |

### 空状態表示

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| イラスト | Image | 空状態のイラスト画像 |
| タイトル | String | 「Get started with Terraform」等 |
| 説明 | String | Terraform状態管理の説明 |
| API URL | String | TerraformバックエンドAPI URL |

### API設定情報

| 項目名 | データ型 | 説明 | ソース |
|--------|----------|------|--------|
| Terraform API URL | String | HTTP Backend URL | `{gitlab_url}/api/v4/projects/{id}/terraform/state` |
| アクセストークンパス | String | PAT設定ページへのリンク | /user_settings/personal_access_tokens |
| ユーザー名 | String | 現在のユーザー名 | current_user.username |

## イベント仕様

### 1-状態削除

**トリガー**: 削除ボタン押下（ゴミ箱アイコン）

**前提条件**:
- `admin_terraform_state`権限を持つ
- 状態がロックされていない

**処理フロー**:
1. 確認ダイアログを表示
2. 状態名の入力確認（安全装置）
3. DELETE APIリクエストを送信
4. 成功時：一覧から削除
5. 失敗時：エラーメッセージを表示

**遷移先**: 同一画面（一覧更新）

### 2-ロック解除

**トリガー**: アンロックボタン押下

**前提条件**:
- `admin_terraform_state`権限を持つ
- 状態がロックされている

**処理フロー**:
1. 確認ダイアログを表示
2. DELETE /lock APIリクエストを送信
3. 成功時：ロック状態を更新
4. 失敗時：エラーメッセージを表示

**遷移先**: 同一画面（状態更新）

### 3-バージョン履歴表示

**トリガー**: バージョン情報クリック

**処理フロー**: バージョン履歴モーダルを表示

**遷移先**: モーダル表示

### 4-ページネーション

**トリガー**: 「次へ」「前へ」ボタン押下

**処理フロー**:
1. GraphQLクエリを実行（カーソルベース）
2. 新しいページの状態を表示

**遷移先**: 同一画面（データ更新）

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | terraform_states | SELECT | Terraform状態の一覧取得 |
| 画面表示 | terraform_state_versions | SELECT | バージョン情報の取得 |
| 削除 | terraform_states | DELETE | Terraform状態の削除 |
| 削除 | terraform_state_versions | DELETE | 関連バージョンの削除 |
| アンロック | terraform_states | UPDATE | ロック情報のクリア |

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

#### terraform_states

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, name, uuid, lock_xid, locked_by_user_id, updated_at, versioning_enabled | project_id = プロジェクトID | ORDER BY name |
| UPDATE | lock_xid, locked_by_user_id | NULL | アンロック時 |
| DELETE | - | id = 状態ID | カスケード削除 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| MSG-001 | 情報 | Terraform states | ページタイトル |
| MSG-002 | 情報 | Get started with Terraform | 空状態時のタイトル |
| MSG-003 | エラー | Something went wrong | データ取得エラー時 |
| MSG-004 | 確認 | Are you sure? | 削除確認ダイアログ |
| MSG-005 | 警告 | State names that include periods may cause issues | 名前にピリオドを含む場合の警告 |

## 例外処理

| 例外 | 原因 | 対処 |
|------|------|------|
| 403 Forbidden | read_terraform_state権限がない | アクセス拒否画面へリダイレクト |
| 423 Locked | ロック中の状態を削除しようとした | エラーメッセージ表示 |
| 404 Not Found | 指定された状態が存在しない | エラーメッセージ表示 |

## 備考

- Terraform状態はGraphQL APIで一覧取得される
- 削除操作はREST API経由で実行される
- ロック機能はTerraformのstate lockingと連携
- 状態名にピリオドを含むと問題が発生する可能性があり、警告アラートが表示される
- アクセストークン（PAT）はTerraformのHTTP Backend認証に使用
- バージョニングにより状態ファイルの履歴が保持される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | state.rb | `app/models/terraform/state.rb` | Terraform::Stateモデルの属性、アソシエーションを確認 |

**読解のコツ**:
- `uuid`で一意識別、`name`はプロジェクト内で一意
- `lock_xid`と`locked_by_user_id`でロック管理
- `versioning_enabled`でバージョン管理の有無を判定
- `latest_version`アソシエーションで最新バージョン取得

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | terraform_controller.rb | `app/controllers/projects/terraform_controller.rb` | indexアクション、認可処理 |
| 2-2 | index.html.haml | `app/views/projects/terraform/index.html.haml` | Vueマウントポイント |
| 2-3 | terraform_helper.rb | `app/helpers/projects/terraform_helper.rb` | js_terraform_list_data |

**主要処理フロー**:
1. **4行目** (controller): `authorize_can_read_terraform_state!`で読み取り権限チェック
2. **9行目** (controller): `index`アクションは空（Vue側でデータ取得）
3. **4-13行目** (helper): `js_terraform_list_data`でVueにデータ渡し

#### Step 3: フロントエンド（Vue.js + GraphQL）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | terraform_list.vue | `app/assets/javascripts/terraform/components/terraform_list.vue` | メインコンポーネント |

**主要処理フロー**:
- GraphQLクエリ`terraformStates`で状態一覧を取得
- 削除はREST APIを使用

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

```
[ブラウザ]
    │
    ├─ GET /terraform (HTML)
    │      └─ TerraformController#index
    │             ├─ authorize_can_read_terraform_state!
    │             └─ HTML response (Vue mount point)
    │                    └─ js_terraform_list_data
    │
    ├─ POST /api/graphql (terraformStates Query)
    │      └─ Resolvers::Terraform::StatesResolver
    │             └─ Terraform::State.ordered_by_name
    │
    ├─ DELETE /api/v4/projects/:id/terraform/state/:name
    │      └─ API::Terraform::State#destroy
    │             └─ Terraform::States::DestroyService
    │
    └─ DELETE /api/v4/projects/:id/terraform/state/:name/lock
           └─ API::Terraform::StateLock#delete
                  └─ Terraform::State.update!(lock_xid: nil)
```

### データフロー図

```
[Terraform状態データ]
    │
    └─ GraphQL terraformStates クエリ
           └─ Terraform::State
                  ├─ name
                  ├─ uuid
                  ├─ locked (lock_xidの有無)
                  ├─ lockedByUser
                  ├─ updatedAt
                  ├─ versionsCount
                  └─ latestVersion
                         ├─ version
                         ├─ createdAt
                         └─ createdByUser
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| state.rb | `app/models/terraform/state.rb` | モデル | Terraform::Stateモデル定義 |
| state_version.rb | `app/models/terraform/state_version.rb` | モデル | バージョンモデル定義 |
| terraform_controller.rb | `app/controllers/projects/terraform_controller.rb` | コントローラー | HTTPリクエスト処理 |
| index.html.haml | `app/views/projects/terraform/index.html.haml` | ビュー | HTMLテンプレート |
| terraform_helper.rb | `app/helpers/projects/terraform_helper.rb` | ヘルパー | ビューデータ生成 |
| terraform_list.vue | `app/assets/javascripts/terraform/components/terraform_list.vue` | Vueコンポーネント | 一覧画面 |
