# バッチ設計書 20-update-openapi-spec.sh

## 概要

本ドキュメントは、KubernetesプロジェクトにおけるOpenAPI仕様の自動生成スクリプト（update-openapi-spec.sh）の設計について記述する。Kubernetes APIのOpenAPIスキーマ（v2/v3）およびAggregated Discovery情報を更新するバッチの仕様を定義する。

### 本バッチの処理概要

update-openapi-spec.shは、実際にkube-apiserverを起動し、そのAPIエンドポイントからOpenAPI仕様とAggregated Discovery情報を取得してリポジトリの静的ファイルを更新する大規模なバッチスクリプトである。

**業務上の目的・背景**：Kubernetesプロジェクトでは、APIのOpenAPI仕様をリポジトリ内の静的ファイル（api/openapi-spec/）として管理している。クライアント生成やAPIドキュメント、バリデーションの基盤となるOpenAPIスキーマを正確に維持するため、実際のAPI Serverから最新のスキーマを取得して更新する必要がある。本スクリプトは、ローカルでetcdとkube-apiserverを起動し、全APIグループ・バージョンのOpenAPI仕様を取得する。

**バッチの実行タイミング**：API型定義の変更後、またはupdate-codegen.sh（No.18）実行後に手動実行される。

**主要な処理内容**：
1. jqコマンドの存在確認、Go環境のセットアップ、etcdのインストール
2. kube-apiserverのビルド（make WHAT=cmd/kube-apiserver）
3. etcdの起動
4. kube-apiserverの起動（AllAlpha=true, AllBeta=true, api/all=true設定）
5. Aggregated Discovery v2情報の取得・保存
6. OpenAPI v2仕様（swagger.json）の取得・保存
7. OpenAPI v3仕様（各APIグループ別）の取得・保存
8. 各APIグループのDiscovery情報の取得・保存
9. クリーンアップ（kube-apiserver/etcdの停止）

**前後の処理との関連**：update-codegen.sh（No.18）によるOpenAPIコード生成が完了した状態で実行される。生成結果はverify-all.sh（No.16）で検証される。

**影響範囲**：api/openapi-spec/配下のswagger.json、v3/配下の各APIグループのOpenAPI仕様ファイル、api/discovery/配下のDiscovery情報。

## バッチ種別

コード生成・API仕様更新

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（API変更後） |
| 実行時刻 | 任意 |
| 実行曜日 | 該当なし |
| 実行日 | 該当なし |
| トリガー | 手動 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Go環境 | Goツールチェインがインストール済みであること |
| jq | jqコマンドが利用可能であること |
| etcd | etcdが利用可能であること（自動インストール） |
| curl | curlコマンドが利用可能であること |
| openssl | opensslコマンドが利用可能であること（ServiceAccountキー生成） |
| ポート | 127.0.0.1:2379（etcd）、127.0.0.1:8050（API Server）が利用可能であること |

### 実行可否判定

スクリプト冒頭の`set -o errexit/nounset/pipefail`によりエラー時は即座に終了する。kube::util::require-jqでjqの存在を検証する。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| ETCD_HOST | 環境変数 | No | 127.0.0.1 | etcdのホスト |
| ETCD_PORT | 環境変数 | No | 2379 | etcdのポート |
| API_PORT | 環境変数 | No | 8050 | API Serverのポート |
| API_HOST | 環境変数 | No | 127.0.0.1 | API Serverのホスト |
| API_LOGFILE | 環境変数 | No | TMP_DIR/openapi-api-server.log | API Serverのログファイル |
| SERVICE_ACCOUNT_LOOKUP | 環境変数 | No | true | ServiceAccountルックアップ |
| SERVICE_ACCOUNT_KEY | 環境変数 | No | TMP_DIR/kube-serviceaccount.key | ServiceAccountキーファイル |
| KUBE_APISERVER_STRICT_REMOVED_API_HANDLING_IN_ALPHA | 環境変数 | No | true | 削除予定APIの厳密なハンドリング |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| cmd/kube-apiserver | Goソースコード | API Serverのソースコード |
| etcd | KV Store | API Serverのバックエンドストレージ |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| api/openapi-spec/swagger.json | JSON | OpenAPI v2仕様 |
| api/openapi-spec/v3/{group}_openapi.json | JSON | OpenAPI v3仕様（APIグループ別） |
| api/discovery/aggregated_v2.json | JSON | Aggregated Discovery v2情報 |
| api/discovery/{group}.json | JSON | APIグループ別Discovery情報 |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | swagger.json / {group}_openapi.json / aggregated_v2.json / {group}.json |
| 出力先 | api/openapi-spec/ および api/discovery/ |
| 文字コード | UTF-8 |
| 区切り文字 | 該当なし（JSON） |

## 処理フロー

### 処理シーケンス

```
1. 環境セットアップ
   ├─ kube::util::require-jq でjq確認
   ├─ kube::golang::setup_env でGo環境初期化
   └─ kube::etcd::install でetcdインストール
2. kube-apiserverのビルド
   └─ make -C "${KUBE_ROOT}" WHAT=cmd/kube-apiserver
3. etcdの起動
   └─ kube::etcd::start
4. kube-apiserverの起動
   ├─ tokenauth.csvの作成（dummy_token）
   ├─ ServiceAccountキーの生成（openssl）
   └─ kube-apiserver起動（AllAlpha=true, AllBeta=true, api/all=true）
5. API Server健全性確認
   └─ /healthzエンドポイントへのポーリング
6. Aggregated Discovery取得
   └─ /apis からAPIGroupDiscoveryListをJSON取得
7. OpenAPI v2仕様取得
   └─ /openapi/v2 からswagger.jsonを取得
8. OpenAPI v3仕様取得
   ├─ /openapi/v3 からグループ一覧取得
   └─ 各グループの/openapi/v3/{group}からスキーマ取得
9. Discovery情報取得
   └─ apiで始まるグループの/{group}からDiscovery情報取得
10. クリーンアップ（trap EXIT SIGINT）
    ├─ kube-apiserver停止
    └─ etcd停止
```

### フローチャート

```mermaid
flowchart TD
    A[スクリプト開始] --> B[環境セットアップ]
    B --> C[kube-apiserver ビルド]
    C --> D[etcd 起動]
    D --> E[kube-apiserver 起動]
    E --> F{/healthz 応答確認}
    F -->|成功| G[Aggregated Discovery 取得]
    F -->|失敗| H[ログ出力してエラー終了]
    G --> I[OpenAPI v2 取得]
    I --> J[OpenAPI v3 全グループ取得]
    J --> K[Discovery 情報取得]
    K --> L[クリーンアップ]
    L --> M[スクリプト終了]
    H --> L
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| etcd初期化 | ローカルetcd | 一時データ | API Serverバックエンド用の一時etcd |

### テーブル別操作詳細

一時的なetcdインスタンスを使用。スクリプト終了時にクリーンアップされる。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | ビルドエラー | kube-apiserverのコンパイル失敗 | Go環境の確認 |
| 1 | 起動エラー | API Serverが/healthzに応答しない | API_LOGFILEの末尾10行を確認 |
| 1 | ポート競合 | 2379/8050ポートが使用中 | ETCD_PORT/API_PORT環境変数で変更 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | /healthzポーリングはkube::util::wait_for_urlで内部リトライ |
| リトライ間隔 | kube::util::wait_for_urlに依存 |
| リトライ対象エラー | API Server起動待ち |

### 障害時対応

API Server起動失敗時は${API_LOGFILE}の末尾10行がエラー出力される。trap EXIT SIGINTによりクリーンアップが自動実行される。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | 該当なし |
| コミットタイミング | 該当なし |
| ロールバック条件 | 該当なし（git resetで復元可能） |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 全APIグループのOpenAPI仕様 |
| 目標処理時間 | 環境依存（数分〜十分程度） |
| メモリ使用量上限 | kube-apiserver + etcdのメモリ消費 |

## 排他制御

etcd/API Serverのポートを専有するため、同一環境での同時実行は不可。ETCD_PORT/API_PORT環境変数でポートを変更することで回避可能。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 進捗ログ | 各フェーズ開始時 | "Starting kube-apiserver"、"Updating aggregated discovery"等 |
| API Serverログ | API Server実行中 | ${API_LOGFILE}に出力 |
| エラーログ | 起動失敗時 | API Serverログの末尾10行 |
| 完了ログ | 正常終了時 | "SUCCESS" |
| クリーンアップログ | 終了時 | "Clean up complete" |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 生成成否 | 終了コード != 0 | CI/CDシステム |

## 備考

- 本スクリプトは実際にkube-apiserverとetcdを起動するため、他のスクリプトより実行に時間とリソースを消費する
- kube-apiserverはAllAlpha=true, AllBeta=true, OpenAPIEnums=false, api/all=trueで起動され、全APIグループのスキーマが生成される
- OpenAPIEnums=falseはクライアント生成のissue #109177が解決するまでの暫定措置
- KUBE_APISERVER_STRICT_REMOVED_API_HANDLING_IN_ALPHA=trueにより、Alpha段階で削除予定のAPIもOpenAPIに含まれる
- 認証はdummy_tokenによるトークン認証、認可はRBACモード
- info.versionは"unversioned"に正規化される（jq -S '.info.version="unversioned"'）
- jq -S で出力がソートされ、差分の安定性が確保される
- trap EXIT SIGINTによりクリーンアップが自動実行される
- ソースコード: `hack/update-openapi-spec.sh`
