{ “expert_role”: “SRE / DevOps Engineer”, “focus”: “Automated Config Generation & JSON/YAML Processing”, “workflow”: “Research-First -> Safe Scripting (set -euo pipefail) -> Pipeline Design -> systemd Integration”, “tools”: [“jq”, “yq”, “curl”, “systemd”, “bash”], “integrity_check”: “Applied trap for cleanup, atomic file writes, and idempotent validation.” }
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
JSON/YAML変換を核とした設定ファイルの自動生成と冪等性の担保
【導入と前提】
API経由で取得したJSONメタデータをYAML形式のシステム設定へ変換し、検証を経て自動反映する堅牢なワークフローを構築します。
OS: GNU/Linux (Ubuntu 22.04 LTS / RHEL 9 動作確認)
必須ツール:
jq(JSONプロセッサ)yq(mikefarah/yq: YAMLプロセッサ)curl(通信クライアント)
【処理フローと設計】
graph TD
A["API Endpoint"] -->|curl -sSfL| B["Raw JSON"]
B -->|jq filter| C["Structured JSON"]
C -->|yq eval| D["Candidate YAML"]
D -->|Validation| E{"Syntax Check"}
E -->|Success| F["Atomic Update /etc/..."]
E -->|Failure| G["Log Error & Trap"]
F -->|systemd trigger| H["Service Reload"]
入力されたJSONはフィルタリングを経て正規化され、YAML変換後にバリデーションを実施します。最終的なファイル配置はアトミック(原子性)を確保するため、一時ファイルからのリネーム操作で行います。
【実装:堅牢な自動化スクリプト】
#!/usr/bin/env bash
# --- 安全な実行のための設定 ---
set -euo pipefail
# -e: エラー発生時に即座に終了
# -u: 未定義変数の参照時にエラー
# -o pipefail: パイプライン途中のエラーも検知
# --- 変数定義 ---
CONFIG_URL="https://api.example.com/v1/config"
TARGET_FILE="/etc/opt/myapp/config.yaml"
TMP_DIR=$(mktemp -d)
TMP_JSON="${TMP_DIR}/source.json"
TMP_YAML="${TMP_DIR}/candidate.yaml"
# --- 後処理のトラップ ---
# スクリプト終了時に(成功・失敗に関わらず)一時ファイルを削除
trap 'rm -rf "$TMP_DIR"' EXIT
echo "[INFO] 設定の同期を開始します..."
# 1. APIからJSON取得 (リトライ処理込み)
# -s: サイレント
# -S: エラー時に詳細を表示
# -f: HTTPエラー(404等)で終了コードを非ゼロにする
# -L: リダイレクトに追従
curl -sSfL --retry 3 --retry-delay 2 "$CONFIG_URL" -o "$TMP_JSON"
# 2. jqによる抽出と正規化
# -e: 抽出結果がnullまたはfalseなら終了コード1を返す
jq -e '.settings | .version = "1.0"' "$TMP_JSON" > "${TMP_JSON}.filtered"
# 3. yqによるYAML変換
# P: プロパティ形式を保持
yq eval -P "${TMP_JSON}.filtered" > "$TMP_YAML"
# 4. バリデーション (例: YAML構文チェック)
if ! yq eval '.' "$TMP_YAML" > /dev/null; then
echo "[ERROR] YAMLの構文チェックに失敗しました" >&2
exit 1
fi
# 5. アトミックなファイル更新
# 既存ファイルと同じディレクトリ内でmvすることで、メタデータ破損を防ぐ
echo "[INFO] 設定ファイルを更新中..."
install -m 644 -o root -g root "$TMP_YAML" "${TARGET_FILE}.new"
mv "${TARGET_FILE}.new" "$TARGET_FILE"
# 6. systemdによるサービスリロード (必要に応じて)
# systemctl reload-or-restart myapp.service || true
echo "[SUCCESS] 同期完了"
systemd タイマー設定例
定期実行を確実に管理するため、cronではなくsystemd timerを推奨します。
# /etc/systemd/system/config-sync.service [Unit] Description=Sync Configuration from API [Service] Type=oneshot ExecStart=/usr/local/bin/sync-config.sh User=root # /etc/systemd/system/config-sync.timer [Unit] Description=Run config sync every hour [Timer] OnCalendar=hourly RandomizedDelaySec=300 Persistent=true [Install] WantedBy=timers.target
【検証と運用】
正常系確認:
systemctl start config-sync.serviceを実行後、ls -l /etc/opt/myapp/config.yamlで更新日時と権限を確認。ログ確認:
journalctl -u config-sync.service -fで実行ログおよび標準エラー出力を追跡。差分確認:
diff /etc/opt/myapp/config.yaml /path/to/backupで意図しない破壊的変更がないか目視確認。
【トラブルシューティングと落とし穴】
権限問題: スクリプトが
/etc配下を書き換える場合、sudoまたは systemd ユニット上でのUser=root設定が必須です。APIのレート制限: 短時間での頻繁な実行は API 429 エラーを招きます。
systemd.timerのRandomizedDelaySecを活用し、リクエストを分散させてください。部分的な失敗:
jqのフィルタリングで想定外のキーが欠落している場合、set -eにより後続の YAML 生成を止め、不完全な設定ファイルがデプロイされるのを防ぎます。環境変数の保護: APIキーが必要な場合は、スクリプト内にハードコードせず、
EnvironmentFile=を用いて systemd から注入してください。
【まとめ】
運用の冪等性を維持するための3つのポイント:
Atomic Write(原子性のある書き込み):
> (リダイレクト)で直接ファイルを上書きせず、mvを使用して書き換え中のファイル参照を防ぐ。Pre-flight Validation(事前検証): ファイルを本番パスへ配置する前に、必ず
yq等でシンタックスチェックを行う。Declarative Management(宣言的管理): 手動の変更は一切行わず、常に API(ソース)を正としてスクリプト経由で状態を収束させる。

