概要
期間指定のある処理をデバッグするためにサーバー側のアプリケーションの日時を任意の日時に固定したいときがあります。
現時点での実現方法を共有します。
他に良いやり方があれば教えてもらえれば幸いです。
結論
Fargate
の制約でサーバーマシンの日時を固定することができなかったので Rails
のアプリケーションコードで固定するしかありませんでした。
タスク定義でデバッグ用の環境変数を設定してサービスをそのタスクに切り替えるという方法です。
# DATETIME_DEBUG_MODE には "2021-01-01 10:00:00" のような Time.zone.parse でパースできる日時の文字列が入る
if ENV['DATETIME_DEBUG_MODE'].present?
require 'active_support/testing/time_helpers'
include ActiveSupport::Testing::TimeHelpers
travel_to(Time.zone.parse(ENV['DATETIME_DEBUG_MODE']))
end
試した他のやり方
date コマンドでマシンの日時を固定する
Fargate
で動くコンテナに対して docker exec
が最近できるようになりました。
参考: Amazon ECS Exec による AWS Fargate, Amazon EC2 上のコンテナへのアクセス
そこでコンテナに対して date
コマンドを実行し、任意の日時を指定しようとしましたが
aws ecs execute-command --command "date 053018002021"
エラーになり上手くいきません。
date: can’t set date: Operation not permitted
docker
で date
コマンドを使うためには privileged
オプションを true にしなければいけないようです。
参考: Dockerコンテナの日付を変更する
しかし、Fargate
では privileged
オプションは有効にできませんでした。
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html#fargate-task-defs
そのため、date
コマンドによる日時設定は諦めました。
環境変数の設定をコマンドで行う
結論
で記載した環境変数による日時指定をタスク切り替えではなく、DATETIME_DEBUG_MODE=2021-01-01 10:00:00 rails server
のように rails server
の起動時に環境変数を付ければわざわざタスク切り替えで数分待つことなく即時に指定日時が反映されるのではと考えました。
そのためにはコンテナで起動している rails server
のプロセスを終了させ、環境変数をつけて再起動させなければなりません。
そこで試しに kill
コマンドで終了させようとしました。
aws ecs execute-command --command "kill 9999"
しかし、aws ecs execute-command
から応答が返って来ず上手くいきませんでした。
また仮に kill
が成功しても aws ecs execute-command
はシェルのパイプが使えないので操作が難しそうです。
結論(再)
ということで
- 環境変数で渡した日時の文字列を
travel_to
する - 環境変数の設定はタスク定義で行い、そのタスクに切り替える
という方法に行きつきました。