paint-brush
AEM パッケージへの DevOps アプローチ: 作成、構成などの自動化@realgpp
新しい歴史

AEM パッケージへの DevOps アプローチ: 作成、構成などの自動化

Giuseppe Baglio11m2025/02/16
Read on Terminal Reader

長すぎる; 読むには

`create-remote-aem-pkg.sh スクリプトは、AEM のパッケージ マネージャー API とのやり取りを自動化し、パッケージの作成、構成、配布に対する構造化されたアプローチを提供します。開発者と管理者向けに設計されており、手動のワークフローを、一貫性と信頼性を重視したコマンドライン駆動型のプロセスに置き換えます。
featured image - AEM パッケージへの DevOps アプローチ: 作成、構成などの自動化
Giuseppe Baglio HackerNoon profile picture

Adobe Experience Manager (AEM) パッケージは、コードや設定から重要なコンテンツまですべてをまとめた強力なコンテナであり、コンテンツ管理の陰の立役者です。しかし、これらのパッケージを手動で作成、設定、ダウンロードするのは、クリックの連続で退屈な作業のように感じられるかもしれません。


このプロセスを数回のキー操作で自動化し、一貫性、速度、信頼性を確保し、負担を軽減できたらどうでしょうか?


AEM 開発者と管理者がパッケージ マネージャー API を操作する方法を一新する Bash スクリプトを紹介します (しゃれです!)。数秒でパッケージを作成し、フィルターを即座に調整し、外科手術のような精度でバックアップを取得することを想像してみてください。コーヒーがちょうどよい温度に冷める前に、すべて完了です。☕


始める前に、一言注意点がありますこの記事は、細部まで詳細に説明し、遠慮なく技術的に掘り下げた内容です。スクリプトのロジックを分析し、AEM API の複雑さを探り、エッジ ケースのトラブルシューティングを行います。すぐにコードを読みたい開発者は、記事の最後まで読んでください。ただし、自動化の仕組みと理由を理解したいのであれば、しっかり準備してください。最後まで掘り下げていきます。🕳️

1. スクリプトの概要

create-remote-aem-pkg.shスクリプトは、AEM のパッケージ マネージャー API とのやり取りを自動化し、パッケージの作成、構成、配布に対する構造化されたアプローチを提供します。開発者と管理者向けに設計されており、手動のワークフローを、一貫性と信頼性を重視したコマンドライン駆動型のプロセスに置き換えます。

1.1 コア機能

  • パッケージ検証: 作成を開始する前に、既存のパッケージをチェックして冗長性を回避します。
  • 動的フィルター インジェクション: パッケージに含めるコンテンツ パス (例: /content/dam/apps ) をプログラムで定義します。
  • ビルド自動化: パッケージのコンパイルをトリガーし、出力を指定されたディレクトリにダウンロードし、バージョン管理のためにファイル名にタイムスタンプを追加します。
  • エラー処理: HTTP 応答、フォルダー パス、および認証を検証し、障害発生時に実用的なフィードバックを提供します。
  • 認証: curl介した基本的な¹ 資格情報ベースの認証をサポートします。

1.2 主な利点

  • 効率性: パッケージの作成、構成、ダウンロードに必要な手動の手順を削減します。
  • 一貫性: 環境間でパッケージ構造と命名規則が統一されていることを保証します。
  • トレーサビリティ: 各段階 (作成、フィルタリング、ビルド、ダウンロード) での詳細なログ記録は、監査とトラブルシューティングに役立ちます。

1.3 実用的応用

  • スケジュールされたバックアップ: cron ジョブと統合して、重要なコンテンツ パスを定期的にアーカイブします。
  • 環境の同期: デプロイメント中に AEM インスタンス間で設定またはコンテンツを複製します。
  • 更新前スナップショット: システム更新を適用する前に、 /etcまたは/appsの安定した状態をキャプチャします。

1.4 前提条件

  • AEM インスタンスへのアクセス (資格情報、サーバー、ポート)。
  • Bash スクリプトと AEM のパッケージ マネージャーに関する基本的な知識。
  • AEM API 経由でパッケージを作成およびダウンロードする権限。

1.5 使用例

./create-remote-aem-pkg.sh admin securepass123 localhost 4502 backup-group "Content Backup" /backups /content/dam /etc/clientlibs


このコマンドは、グループbackup-groupの下に/content/dam/etc/clientlibsを含む「Content Backup」という名前のパッケージを作成し、出力を/backupsディレクトリに保存します。

2. スクリプトの詳細

create-remote-aem-pkg.shスクリプト (記事の下部にあります) を分析して、それが AEM パッケージ管理をどのようにオーケストレーションするかを理解しましょう。その構造、主要な機能、ワークフロー ロジックに焦点を当てます。これは、ツールをカスタマイズまたはデバッグしようとしている開発者に最適です。

2.1 コア機能

  • _log() : 明確な監査証跡を残すために、メッセージの先頭にタイムスタンプを付けるユーティリティ関数。
 _log () { echo "[$(date +%Y.%m.%d-%H:%M:%S)] $1" }


重要である理由: すべてのアクション (「パッケージのビルド」など) がコンテキストとともにログに記録され、トラブルシューティングが簡素化されます。

  • check_last_exec() : 終了コードと API 応答をチェックして、以前のコマンドの成功を検証します。
 check_last_exec () { # Checks $? (exit status) and $CURL_OUTPUT for errors if [ "$status" -ne 0 ] || [[ $output =~ .*success\":false* ]]; then _log "Error detected!"; exit 1; fi }

重要である理由: 認証の問題や無効なパスなどの重大なエラーが発生した場合に実行を停止することで、サイレント障害を防止します。

2.2 入力パラメータ

このスクリプトは、7 つの位置引数とそれに続く動的フィルターを受け入れます。

 USR="$1" # AEM username PWD="$2" # AEM password SVR="$3" # Server host (eg, localhost) PORT="$4" # Port (eg, 4502) PKG_GROUP="$5" # Package group (eg, "backups") PKG_NAME="$6" # Package name (eg, "dam-backup") BK_FOLDER="$7" # Backup directory (eg, "/backups") shift 7 # Remaining arguments become filters (eg, "/content/dam")


位置引数はシンプルさを保証し、 shift可変フィルター パスを柔軟に処理します。

2.3 パッケージの検証と作成

  • 名前のサニタイズ: URL の問題を回避するために、 PKG_NAME内のスペースをアンダースコアに置き換えます。
 PKG_NAME=${PKG_NAME// /_}
  • 既存のパッケージを確認する: curl使用して AEM の API 経由でパッケージを一覧表示し、重複した作成を回避します。
 if [ $(curl ... | grep "$PKG_NAME.zip" | wc -l) -eq 1 ]; then _log "Package exists—skipping creation." else curl -X POST ... # Creates the package fi

2.4 動的フィルタ構成

入力パスからフィルターの JSON 配列を構築します。

 FILTERS_PARAM="" for i in "${!FILTERS[@]}"; do FILTERS_PARAM+="{\"root\": \"${FILTERS[$i]}\", \"rules\": []}" # Adds commas between entries, but not after the last done


出力例:

[{"root": "/content/dam"}, {"root": "/apps"}]

この JSON は、AEM の/crx/packmgr/update.jspエンドポイントを介してパッケージ定義に挿入されます。

2.5 ビルドとダウンロードのワークフロー

  • パッケージをビルドする: AEM のbuildコマンドを使用してコンパイルをトリガーします。

curl -X POST … -F "cmd=build"


: スクリプトはビルドが完了するまで待機してから続行します。

  • ダウンロード: curl使用して.zipを取得し、タイムスタンプ付きのファイル名で保存します。
 BK_FILE="$PKG_NAME-$(date +%Y%m%d-%H%M%S).zip" curl -o "$BK_FOLDER/$BK_FILE" ...

3. エラー処理、セキュリティに関する注意事項、ログ記録

堅牢なエラー処理とログ記録は、 create-remote-aem-pkg.shなどの無人スクリプトにとって重要であり、障害が早期に検出され、明確にログに記録されることを保証します。ここでは、スクリプトが予期しない問題から保護し、実用的な洞察を提供する方法について説明します。

3.1 ログ記録メカニズム

  • タイムスタンプ付きログ: _log関数は、すべてのメッセージの先頭に[YYYY.MM.DD-HH:MM:SS]タイムスタンプを付け、デバッグ用の監査証跡を作成します。

_log "Starting backup process..." # Output: [2023.10.25-14:30:45] Starting backup process...


重要である理由: タイムスタンプは、スクリプトのアクティビティを AEM サーバー ログまたは外部イベント (例: cron ジョブのスケジュール) と関連付けるのに役立ちます。

  • 詳細出力: パッケージの作成、フィルターの更新、ダウンロードなどの重要な手順は、進行状況を追跡するために明示的にログに記録されます。

3.2 エラー検証ワークフロー

飛行前チェック:

  • 続行する前に、バックアップ フォルダー ( BK_FOLDER ) の存在を検証します。
 if [ ! -d "$BK_FOLDER" ]; then _log "Backup folder '$BK_FOLDER' does not exist!" && exit 1 fi
  • URL の問題を回避するためにPKG_NAMEサニタイズします (例: スペースがアンダースコアに置き換えられる)。


APIレスポンス検証:

check_last_exec関数は、シェルの終了コード ( $? ) と AEM API 応答の両方を調べます。

check_last_exec "Error message" "$CURL_OUTPUT" $CURL_STATUS

  • 終了コード: ゼロ以外の値 (例: curlネットワーク障害) は即時に終了します。


  • API エラー: AEM 出力でsuccess\":false JSON 応答または "HTTP ERROR" 文字列を検出します。


3.3 HTTP ステータスの検証: パッケージをダウンロードするときに、スクリプトは200ステータス コードをチェックします。

 if [ "$(curl -w "%{http_code}" ...)" -eq "200" ]; then # Proceed if download succeeds else _log "Error downloading the package!" && exit 1 fi

3.4 一般的な障害シナリオ

  • 無効な資格情報: check_last_exec 401 Unauthorized応答をキャッチし、明確なエラー メッセージを表示して終了します。
  • 無効なフィルター パス: AEM API はsuccess:falseを返し、スクリプトは「フィルターの追加エラー」をログに記録して終了します。
  • ディスクがいっぱいです: BK_FILEの書き込みに失敗し、 -sフラグを使用してファイル サイズをチェックし、終了する前に警告します。
  • AEM インスタンスに到達できません: curlゼロ以外のコードで終了し、スクリプトは「パッケージのビルド エラー」をログに記録します。

3.5 セキュリティに関する考慮事項

  • SSL 証明書バイパス: スクリプトは簡潔にするためにcurl -k使用し、SSL 検証をスキップします。本番環境での推奨事項: CA バンドルを指定するには、 --cacertに置き換えます。


  • プレーンテキスト パスワード: 資格情報は引数として渡され、プロセス ログに表示される可能性があります。軽減策: 環境変数またはシークレット ボールト (例: $AEM_PASSWORD ) を使用します。

3.6 デバッグのヒント

  • 詳細出力を有効にする: スクリプトの開始時にset -xを一時的に追加して、実行されたコマンドを出力します。
  • API 呼び出しを手動でテストする: スクリプト外で重要なcurlコマンドを実行して問題を切り分ける
  • ログの検査: スクリプトの出力をファイルにリダイレクトして後で分析します。

./create-remote-aem-pkg.sh ... >> /var/log/aem_backup.log 2>&1

4. ワークフローに合わせてツールを調整する

create-remote-aem-pkg.shスクリプトは、チームのニーズに合わせて変更できる基盤として、出発点となるように設計されています。以下は、機能を拡張したり、特定のユースケースに適応したりするための一般的なカスタマイズと実装ガイダンスです。

4.1 バックアップファイル名の形式の調整

デフォルトのファイル名ではタイムスタンプ ( $PKG_NAME-$(date +%Y%m%d-%H%M%S).zip ) が使用されます。これを変更して、環境名、プロジェクト ID、またはセマンティック バージョン管理を含めます。

 # Example: Include environment (eg, "dev", "prod") BK_FILE="${PKG_NAME}-${ENV}-$(date +%Y%m%d).zip" # Example: Add Git commit SHA for traceability COMMIT_SHA=$(git rev-parse --short HEAD) BK_FILE="${PKG_NAME}-${COMMIT_SHA}.zip"

ヒント: 日付/時刻の形式では、ファイル名に禁止されている文字 (Windows のコロン:など) が使用されていないことを確認してください。

4.2 フィルターの拡張または変更

スクリプトは動的パスをフィルターとして受け入れますが、頻繁に使用するパスをハードコードしたり、除外を追加したりすることもできます。

 # Hardcode essential paths (eg, "/var/audit") DEFAULT_FILTERS=("/content/dam" "/apps" "/var/audit") FILTERS=("${DEFAULT_FILTERS[@]}" "${@}") # Merge with command-line inputs # Add exclusion rules (requires AEM API support) FILTERS_PARAM+="{\"root\": \"${FILTERS[$i]}\", \"rules\": [{\"modifier\": \"exclude\", \"pattern\": \".*/test/*\"}]}"

4.3 セキュリティの強化


プレーンテキストのパスワードを避ける:

環境変数またはシークレット マネージャーを使用して資格情報を挿入します。

 # Fetch password from environment variable PWD="$AEM_PASSWORD" # Use AWS Secrets Manager (example) PWD=$(aws secretsmanager get-secret-value --secret-id aem/prod/password --query SecretString --output text)


SSL検証を強制する:
curl -k (安全でない) を信頼できる CA 証明書に置き換えます。

 curl --cacert /path/to/ca-bundle.crt -u "$USR":"$PWD" ...

4.4 ビルド後のアクションの追加

ダウンロードが成功した後に下流のプロセスをトリガーするようにスクリプトを拡張します。

 # Example: Upload to cloud storage aws s3 cp "$BK_FOLDER/$BK_FILE" s3://my-backup-bucket/ # Example: Validate package integrity CHECKSUM=$(sha256sum "$BK_FOLDER/$BK_FILE" | cut -d ' ' -f 1) _log "SHA-256 checksum: $CHECKSUM" # Example: Clean up old backups (retain last 7 days) find "$BK_FOLDER" -name "*.zip" -mtime +7 -exec rm {} \;

4.5 通知アラートの追加

Slack、電子メール、または監視ツールを介してチームに成功/失敗を通知します。

 # Post to Slack on failure curl -X POST -H 'Content-type: application/json' \ --data "{\"text\":\"🚨 AEM backup failed: $(hostname)\"}" \ https://hooks.slack.com/services/YOUR/WEBHOOK/URL # Send email via sendmail if [ $? -ne 0 ]; then echo "Subject: Backup Failed" | sendmail [email protected] fi

5. 結論

AEM パッケージの管理は、手動でエラーが発生しやすい作業である必要はありません。create create-remote-aem-pkg.sh aem-pkg.sh スクリプトを使用すると、パッケージの作成、フィルタリング、配布を、合理化された繰り返し可能なプロセスに変換できます。このツールは、時間を節約するだけでなく、AEM 操作の一貫性、信頼性、スケーラビリティを実現します。

重要なポイント

  1. 自動化のメリット: スクリプトは反復的な GUI 操作を排除することで人的エラーを減らし、チームがより価値の高いタスクに集中できるようにします。


  2. 柔軟性が重要: 重要なコンテンツのバックアップ、環境の同期、更新の準備など、スクリプトは最小限の調整でさまざまなユースケースに適応します。


  3. 回復力が鍵: 組み込みのログ記録、エラー チェック、セキュリティの考慮事項により、問題が発生した場合でもスクリプトが予測どおりに動作することが保証されます。


優れたツールは、現実世界の課題から生まれます。このスクリプトは出発点です。チームのニーズが拡大するにつれて構築する基盤として考えてください。単独の開発者であっても、大規模な DevOps チームの一員であっても、このような自動化は、コードへの小さな投資が生産性と安心感において大きな利益をもたらすことを実証しています。


次のステップに進む準備はできていますか?

  • 🛠️カスタマイズ:セクション 6 をガイドとして使用してスクリプトをカスタマイズします。
  • 🔍監査: 既存の AEM ワークフローをレビューして自動化の機会を探します。
  • 🤝共有: チームを指導したり、変更内容についてブログ記事を書いたりします。


最後までお読みいただきありがとうございました。さあ、自動化を進めましょう! 🚀

付録

完全なコード

#!/bin/bash set -eo pipefail # The script will create a package thought the package manager api: # - The package is created, if not already present # - Package filters are populated accordingly to specified paths # - Package is builded # - Package is download to the specified folder _log () { echo "[$(date +%Y.%m.%d-%H:%M:%S)] $1" } check_last_exec () { local message="$1" local output="$2" local status=$3 if [ "$status" -ne 0 ]; then echo && echo "$message" && echo exit 1 fi if [[ $output =~ .*success\":false* ]] || [[ $output =~ .*"HTTP ERROR"* ]]; then _log "$message" exit 1 fi } USR="$1" PWD="$2" SVR="$3" PORT="$4" PKG_GROUP="$5" PKG_NAME="$6" BK_FOLDER="$7" shift 7 # The following paths will be included in the package FILTERS=($@) BK_FILE=$PKG_NAME"-"$(date +%Y%m%d-%H%M%S).zip _log "Starting backup process..." echo "AEM instance: '$SVR':'$PORT' AEM User: '$USR' Package group: $PKG_GROUP Package name: '$PKG_NAME' Destination folder: $BK_FOLDER Destination file: '$BK_FILE' Filter paths: " printf '\t%s\n\n' "${FILTERS[@]}" if [ ! -d "$BK_FOLDER" ]; then _log "Backup folder '$BK_FOLDER' does not exist!" && echo exit 1 fi PKG_NAME=${PKG_NAME// /_} check_last_exec "Error replacing white space chars from package name!" "" $? || exit 1 _log "Removed whitespaces from package name: '$PKG_NAME'" BK_FILE=$PKG_NAME.zip _log "Backup file: '$BK_FILE'" _log "Creating the package..." if [ $(curl -k -u "$USR":"$PWD" "$SVR:$PORT/crx/packmgr/service.jsp?cmd=ls" 2>/dev/null | grep "$PKG_NAME.zip" | wc -l) -eq 1 ]; then _log " Package '$PKG_GROUP/$PKG_NAME' is already present: skipping creation." else curl -k --silent -u "$USR":"$PWD" -X POST \ "$SVR:$PORT/crx/packmgr/service/.json/etc/packages/$PKG_GROUP/$PKG_NAME?cmd=create" \ -d packageName="$PKG_NAME" -d groupName="$PKG_GROUP" check_last_exec " Error creating the package!" "" $? _log " Package created" fi # create filters variable FILTERS_PARAM="" ARR_LEN="${#FILTERS[@]}" for i in "${!FILTERS[@]}"; do FILTERS_PARAM=$FILTERS_PARAM"{\"root\": \"${FILTERS[$i]}\", \"rules\": []}" T=$((i+1)) if [ $T -ne $ARR_LEN ]; then FILTERS_PARAM=$FILTERS_PARAM", " fi done # add filters _log "Adding filters to the package..." CURL_OUTPUT=$(curl -k --silent -u "$USR":"$PWD" -X POST "$SVR:$PORT/crx/packmgr/update.jsp" \ -F path=/etc/packages/"$PKG_GROUP"/"$PKG_NAME".zip -F packageName="$PKG_NAME" \ -F groupName="$PKG_GROUP" \ -F filter="[$FILTERS_PARAM]" \ -F "_charset_=UTF-8") CURL_STATUS=$? # Pass the status to the check_last_exec function check_last_exec "Error adding filters to the package!" "$CURL_OUTPUT" $CURL_STATUS _log " Package filters updated successfully." # build package _log "Building the package..." CURL_OUTPUT=$(curl -k -u "$USR":"$PWD" -X POST \ "$SVR:$PORT/crx/packmgr/service/script.html/etc/packages/$PKG_GROUP/$PKG_NAME.zip" \ -F "cmd=build") check_last_exec " Error building the package!" "$CURL_OUTPUT" $? _log " Package built." # download package _log "Downloading the package..." if [ "$(curl -w "%{http_code}" -o "$BK_FOLDER/$BK_FILE" -k --silent -u "$USR":"$PWD" "$SVR:$PORT/etc/packages/$PKG_GROUP/$PKG_NAME.zip")" -eq "200" ]; then if [ -f "$BK_FOLDER/$BK_FILE" ] && [ -s "$BK_FOLDER/$BK_FILE" ]; then _log " Package $BK_FILE downloaded in $BK_FOLDER." exit 0 fi fi _log " Error downloading the package!" exit 1


参考文献

[¹] curl -kで SSL 検証をスキップするのはテストには便利ですが、本番環境ではより堅牢なもの (たとえば--cacert ) が必要になります。


[²] AEM パッケージ マネージャー公式ドキュメント