Discourse インスタンスを数ヶ月前に作成した際、一時的に管理画面の設定のみで「S3」(当社の場合は DigitalOcean Spaces)を有効にしましたが、app.yml ファイルに DISCOURSE_ 構成オプションを一切設定しませんでした。すべてのデータを S3 に移行したわけではありませんが、有効化中に画像の大部分が書き込まれました。現在、さまざまな理由(ここでは詳細は省略します)から、すべてのデータを S3 から移行したいと考えています。
(これまではサポート投稿のように聞こえるかもしれませんが、そうではありません…)
最近マージされた PR で、uploads:migrate_from_s3 をラップする単純な Rake タスク uploads:batch_migrate_from_s3 を追加し、1 ポスト分の画像のみを移行するなどの小規模なバッチ処理を実行できるようにしました。これを実行したところ、私のタスクが呼び出す upload:migrate_from_s3 が、UI からは利用できない S3 設定を discourse.conf に想定していることが判明しました。
$ bin/rake 'uploads:batch_migrate_from_s3[1]' --trace
** Invoke uploads:batch_migrate_from_s3 (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute uploads:batch_migrate_from_s3
Migrating uploads from S3 to local storage for 'default'...
rake aborted!
NoMethodError: undefined method `downcase' for nil:NilClass
/var/www/discourse/app/models/global_setting.rb:107:in `s3_bucket_name'
/var/www/discourse/app/models/site_setting.rb:157:in `absolute_base_url'
/var/www/discourse/lib/tasks/uploads.rake:138:in `migrate_from_s3'
/var/www/discourse/lib/tasks/uploads.rake:118:in `block in migrate_all_from_s3'
最適な解決策は何でしょうか?
- S3 の設定は常に app.yml ファイル内の
DISCOURSE_環境変数を通じて行い、コンテナビルド時にconfig/discourse.confに書き込むことが想定されており、現在それを設定してアプリを再構築すべきである。(rake への環境変数の入力がここでGlobalSettingsを設定していないことも確認しました。これも試しましたが、SiteSettingsだけの設定で動作していたことは見落としであり、意図しない動作だったと考えられます。)既存のコンテナ内のconfig/discourse.confにs3_bucketを追加してテストしたところ、エラーは解消されました。 SiteSetting.s3_upload_bucketが設定されているがGlobalSetting.s3_bucketがnilの場合、GlobalSetting.s3_bucketをSiteSetting.s3_upload_bucketに設定するように移行タスクをさらに修正する。これが正しいと判断されれば、比較的簡単な PR になると思いますが、まだ詳しく調べていません。編集:uploads:migrate_from_s3内でGlobalSetting.s3_bucketを変更しようとしましたが、アクセサがないため動作しませんでした。GlobalSetting.s3_bucketがnilの場合、SiteSetting.absolute_base_urlがSiteSetting.s3_upload_bucketを使用するようにする。これは正しい設定として意図されたものなのでしょうか?s3_bucketをサイト設定で設定可能にし、UI からアクセスできるようにする。
1 番目は単なるサイト設定の問題であり、おそらくそれを実行するつもりです。2 番目が良い代替案とみなされるなら、PR を作成することに喜んで挑戦します。ただし、私はまだこのプロジェクトに慣れていないため、後者の 2 つのようにコアな変更を行う自信がありません。設定オブジェクトの動作に関する期待値が少し不明瞭だからです。
明確にしておきますが、私の問題は簡易的な回避策で解決済みです。ただ、それが必要だったことに驚きました。