Search code examples
rubyamazon-s3carrierwavefog

Local (outside EC2) testing with Fog/Carrierwave and IAM instance profiles?


I understand that I can configure fog to use IAM instance profiles (I’m uploading to S3 via fog/carrierwave) by passing use_iam_profile => true. What I haven’t yet figured out is how to test my code outside of an EC2 instance, like on my local machine. Is there a strategy for this that people are using?


Solution

  • I don't know how others might be doing this, but this is the strategy I've come up with. I have a config.yml that looks like this:

    default: &default
      aws:
        s3:
          bucket: 'my-production-bucket'
      fog: &fog
        credentials: &credentials
          provider: 'AWS'
          region: 'us-east-1'
    
    development: &development
      <<: *default
      aws:
        s3:
          bucket: 'my-dev-bucket'
      fog:
        <<: *fog
        credentials:
          <<: *credentials
          aws_access_key_id: 'ID_WITH_DEV_BUCKET_ACCESS_ONLY'
          aws_secret_access_key: 'CORRESPONDING_SECRET'
    
    test:
      <<: *development
    
    production:
      <<: *default
      fog:
        <<: *fog
        credentials:
          <<: *credentials
          use_iam_profile: true
    

    I'm also using this trick in app_config.rb to load my config.yml file (not required for this solution, but it'll make the next part make more sense to you):

    require 'ostruct'
    require 'yaml'
    
    all_config = YAML.load_file(Rails.root.join('config', 'config.yml')) || {}
    env_config = all_config[Rails.env] || {}
    AppConfig = OpenStruct.new(env_config)
    

    Then, in my config/initializers/carrier_wave.rb file:

    CarrierWave.configure do |config|
      config.fog_credentials = AppConfig.fog['credentials'].symbolize_keys
      config.fog_directory  = AppConfig.aws['s3']['bucket']
    end
    

    Notes:

    1. The symbolize_keys call there is necessary because by default I wind up with a hash with strings as keys, and Fog is looking for symbols.
    2. Yes, I'm checking in an app ID and secret, but you don't have to; you could do this with environment variables instead. Personal choice here, and I may change it later.
    3. This works as expected locally, but I haven't tried it in EC2 yet. Since in each Rails environment the CarrierWave::Uploader::Base.fog_credentials hash comes out exactly as I expect it to, it should work just fine when I get there.

    The end result is that in all environments, the AppConfig.fog['credentials'] hash gets the same :region and :provider. In development, it also contains the ID and secret. In production it doesn't contain the ID or secret, but instead gets :use_iam_profile => true