CLIにおけるJSON/YAML変換の自動化と設定ファイル生成の堅牢化

Tech

{ “status”: “draft”, “topic”: “JSON/YAML CLI Conversion & Auto-generation”, “role”: “SRE/DevOps Engineer”, “tools”: [“jq”, “yq”, “bash”, “systemd”], “security”: “low-privilege-execution, atomic-writes” }

本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。

CLIにおけるJSON/YAML変換の自動化と設定ファイル生成の堅牢化

【導入と前提】

API等から取得したJSON形式の構成情報をYAMLへ変換し、インフラ設定ファイルとして自動生成・配置する一連のオペレーションを堅牢化します。

  • OS: GNU/Linux (Ubuntu/RHEL)

  • 必須ツール: jq (1.6+), yq (mikefarah/yq v4+), curl

  • 権限: 設定配置先への書き込み権限(必要に応じてsudo)

【処理フローと設計】

graph TD
A["Remote API / JSON Input"] -->|curl & jq validation| B{"Data Integrity Check"}
B -->|Valid| C["yq Conversion"]
B -->|Invalid| D["Error Trap & Alert"]
C -->|Atomic Write| E["Local YAML Config"]
E -->|systemd notify/restart| F["Service Reload"]

入力データの整合性をjqで検証した後、yqを用いてYAMLへ変換。競合や不完全な書き込みを防ぐため、一時ファイルを介したアトミックな置換処理を行います。

【実装:堅牢な自動化スクリプト】

#!/usr/bin/env bash

# ==============================================================================


# 設定ファイル自動生成スクリプト (JSON to YAML)


# ==============================================================================

set -euo pipefail # エラー発生時停止、未定義変数参照禁止、パイプ途中エラーの捕捉
trap 'rm -f "$TMP_FILE"' EXIT # 終了時に一時ファイルを確実に削除

# 変数定義

API_URL="https://api.example.com/v1/config"
TARGET_CONF="/etc/myapp/config.yaml"
TMP_FILE=$(mktemp /tmp/config.XXXXXX.yaml)

echo "--- Starting configuration update ---"

# 1. JSONデータの取得と検証


# curl: -s(静音), -S(エラー表示), -L(リダイレクト追従), --retry(リトライ)


# jq: -e(終了コードで成否判定)

RAW_JSON=$(curl -sSL --retry 3 "${API_URL}")
echo "${RAW_JSON}" | jq -e . > /dev/null || { echo "Error: Invalid JSON received"; exit 1; }

# 2. JSONからYAMLへの変換と特定フィールドの加工


# yq: evalでJSON入力を受け取り、YAML形式で出力

echo "${RAW_JSON}" | yq eval -P -o=yaml . > "$TMP_FILE"

# 3. 差分チェックとアトミックな更新

if diff -q "$TARGET_CONF" "$TMP_FILE" > /dev/null 2>&1; then
    echo "No changes detected. Skipping update."
else
    echo "Changes detected. Updating configuration..."

    # 権限を維持しつつアトミックに置換

    install -m 644 -o root -g root "$TMP_FILE" "$TARGET_CONF"

    # 4. サービスのリロード (systemd)

    if systemctl is-active --quiet myapp.service; then
        systemctl reload myapp.service
        echo "Service reloaded successfully."
    fi
fi

systemdタイマーによる定期実行例 (/etc/systemd/system/config-sync.timer)

[Unit]
Description=Daily configuration sync from API

[Timer]
OnCalendar=daily
RandomizedDelaySec=1h
Persistent=true

[Install]
WantedBy=Timers.target

【検証と運用】

  1. 正常系の確認:

    • スクリプト実行後、yq eval '.' /etc/myapp/config.yaml でYAMLの構文が正しいことを確認します。

    • journalctl -u config-sync.service で実行ログ(標準出力)を確認します。

  2. エラー時の対応:

    • ネットワークエラーの場合、curl のリトライにより一時的な瞬断は許容されます。

    • JSONが不正な場合、jq -e により後続の書き込み処理はスキップされます。

【トラブルシューティングと落とし穴】

  • 権限問題: install コマンドを使用せず mv すると、/etc 下で本来必要な所有者/グループ属性が壊れる可能性があります。必ず install または cp -p を検討してください。

  • 環境変数の漏洩: APIトークンをスクリプトに直書きせず、systemdEnvironmentFile または Secret 管理ツールから読み込むように設計してください。

  • yqのバージョン互換性: mikefarah/yqkislyuk/yq (jq wrapper) はコマンドライン引数が全く異なります。本稿は mikefarah/yq v4系を前提としています。

【まとめ】

運用の冪等性を維持するための3つのポイント:

  1. 検証の分離: ファイルを上書きする前に必ず jqyq の終了コードでデータの健全性を確認する。

  2. 一時ファイルの使用: 書き込み中のプロセス停止による「中途半端な設定ファイル」の発生を防ぐ。

  3. 差分確認: 変更がない場合はリロードを行わず、システムへの不要な刺激(ダウンタイムリスク)を最小化する。

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

タイトルとURLをコピーしました