Repository navigation
ActiveStorage Mirror Issue #562
Description
I am trying to set up ActiveStorage mirror so that I can migrate from S3 into my Cloudinary. When I try to run the mirror check and upload, I'm getting an error, "RuntimeError (Must supply cloud_name)"
If I check Cloudinary.config, I get all the correct info:
#<OpenStruct cloud_name="airjoshb", api_key="my_key", api_secret="my_key", private_cdn=false, false=false, secure=true, enhance_image_tag=true, static_file_support=false>
But if I check Cloudinary.config.cloud_name, it returns false
If I try to run the mirror command locally, I get a bit more info in that it is confirming the file isn't in my mirror on Cloudinary
Cloudinary Storage (4.0ms) Checked if file exists at key: 3uxbbrz9kh4mw7iq2z2xzyuo1w2z (no) Mirror Storage (4.5ms) Mirrored file at key: 3uxbbrz9kh4mw7iq2z2xzyuo1w2z (checksum: DSAVwrDMF+tj9ncc9pCX2A==) /Users/joshua/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/cloudinary-2.2.0/lib/cloudinary/api.rb:1269:in call_api': Must supply cloud_name (RuntimeError)`
Any thoughts on why it finds the cloud_name but is returning false when I try to use it?
ruby 3.0.0p0
Rails 7.0.4
cloudinary (2.2.0)
activestorage (7.0.4)
I have tried all manner of configurations, using the cloudinary.yml in the config folder
development:
cloud_name: airjoshb
api_key: ENV.fetch('CLOUDINARY_KEY_ID')
api_secret: ENV.fetch('CLOUDINARY_ACCESS_KEY')
enhance_image_tag: true
static_file_support: false
production:
cloud_name: airjoshb
api_key: ENV.fetch('CLOUDINARY_KEY_ID')
api_secret: ENV.fetch('CLOUDINARY_ACCESS_KEY')
enhance_image_tag: true
static_file_support: true
In an initializer, cloudinary.rb where the env includes the key:key@cloud_name format
require 'cloudinary'
Cloudinary.config_from_url("cloudinary://ENV.fetch('CLOUDINARY_URL')")
Cloudinary.config do |config|
config.secure = true
config.enhance_image_tag = true
config.static_file_support= false
end
And, my storage.yml is super simple, as the gem seems to prefer using the initializer
cloudinary:
service: Cloudinary
folder: switch-bakery
# Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
amazon:
service: S3
access_key_id: <%= ENV.fetch('AWS_ACCESS_KEY_ID') %>
secret_access_key: <%= ENV.fetch('AWS_SECRET_ACCESS_KEY') %>
region: 'us-west-1'
bucket: <%= ENV.fetch('S3_BUCKET_NAME') %>
production:
service: Mirror
primary: amazon
mirrors:
- cloudinary
Activity
const-cloudinary commentedon Oct 1, 2024
@airjoshb , thank you for reporting the issue!
This is indeed weird.
Did it happen in the previous version of the SDK, for example: 2.1.2 ?
In the latest version we added explicit
ostructdependency, maybe that could affect something.In addition you can also try to pass
cloud_name,api_keyandapi_secretin yourstorage.ymlairjoshb commentedon Oct 2, 2024
Thanks for getting back to me. I hadn't tried this particular setup in the previous SDK. I'll try downgrading and see if that works. I have another project that could be on the older SDK and that works flawlessly, which is why I have been so stumped! I did try setting everything in the storage.yml with the same effect.
One difference I noticed between the two in calling the config is that in the working project, there is no false=false, which shows up no matter how I configure in the newer setup ... maybe a hint?
#<OpenStruct cloud_name="airjoshb", api_key="my_key", api_secret="my_key", private_cdn=false, false=false, secure=true, enhance_image_tag=true, static_file_support=false>const-cloudinary commentedon Oct 3, 2024
@airjoshb when setting those values in
storage.ymlthose values are not passed to the global config, but stored as@optionsin the service class and then they get passed to the SDK directly.const-cloudinary commentedon Oct 3, 2024
@airjoshb I was able to setup the mirror storage, set a few different cloudinary configurations in
storage.ymlAnd both worked for me.
airjoshb commentedon Oct 4, 2024
Ok- I was able to get the direct mirroring to work using the storage.yml configuration. The point of setting this up was to migrate from S3 to Cloudinary and so I was using the mirror_later feature of active storage to accomplish this, but I get the same error for cloud_name when I run it. Current status:
And to ensure clarity, I am passing the cloud_name in the storage.yml, per your original comment. Thanks for all the help!
airjoshb commentedon Oct 12, 2024
hi @const-cloudinary - any additional thoughts on this?
const-cloudinary commentedon Oct 14, 2024
Hey @airjoshb ,
There are actually 2 ways configuring Cloudinary using env variables, using
CLOUDINARY_URLand using separate env variables, see:cloudinary_gem/lib/cloudinary/config.rb
Line 9 in c50fa14
I would check
CLOUDINARY_CLOUD_NAMEenv variable in your environment.airjoshb commentedon Oct 14, 2024
Thanks, @const-cloudinary
This all feels quite strange, as I am now getting an error: Cloudinary::BaseApi::AuthorizationRequired: unknown api_key
I have taken your advice and set up env variables two different ways to see if it would make a difference, one with all of the ENV variables separate
and get the proper keys, matching up to the API keys in the console
Running mirror_later, the job is now enqueued successfully
but when the job runs I get, Cloudinary::BaseApi::AuthorizationRequired: unknown api_key
I get the same error if setting up using CLOUDINARY_URL
I was thinking that perhaps the key wasn't working, but the uploading works directly in the mirror. Thanks for your patience and help!
const-cloudinary commentedon Oct 16, 2024
@airjoshb, this is really strange.
One thing I can think of is that maybe
ActiveStorage::MirrorJobis running in a separate process that does not inherit environment variables and that's why nothing is initialized.Maybe try overriding the default
MirrorJobas follows:Or just print variables and check what you see there.
Another way would be to override
CloudinaryServiceand then in your
storage.ymlSimilarly you can modify
def upload(key, io, checksum: nil, **options)or other methods and pass credentials explicitly.
Please let me know if it works for you.