Search code examples
rubyfog

Set options conditionally with block


I am building a module that provides some functionality for interacting with the AWS CloudWatch service using the Fog gem. If you do not specify credentials, it will automatically use whatever is set in ENV or use the IAM role of the instance the code is running on. Other times, I would like to explicitly pass credentials to access other AWS accounts. Here is an example class demonstrating how I'd like this to work:

class MyAlarmGetter
  include CloudWatchClient

  default_account_alarms = get_all_alarms

  other_account_alarms = with_aws_credentials(account2) do
    get_all_alarms
  end

  def account2
    {
      aws_access_key_id: 'abc123',
      aws_secret_access_key: 'abc123'
    }
  end
end

This is what the module looks like so far:

module CloudWatchClient
  def with_aws_credentials(creds)
    # Set credentials here!
    yield
  end

  def get_all_alarms
    cloud_watch_client.alarms.all
  end

  def cloud_watch_client(creds = ENV['FOG_CREDENTIAL'] ? {} : { use_iam_profile: true })
    Fog::AWS::CloudWatch.new(creds)
  end
end

I'm stuck on figuring out a way to be able to only override the default credentials inside the context of the with_aws_credentials block.


Solution

  • To support this kind of interface you could save the creds parameter into an instance variable, e.g. @creds

    module CloudWatchClient
      def with_aws_credentials(creds)
        # set given context
        @creds = creds
    
        result = yield
    
        # reset context
        @creds = nil
    
        result 
      end
    
      def get_all_alarms
        cloud_watch_client.alarms.all
      end
    
      def cloud_watch_client(creds = ENV['FOG_CREDENTIAL'] ? {} : { use_iam_profile: true })
        # check if context is given and use it
        creds = @creds || creds
    
        Fog::AWS::CloudWatch.new(creds)
      end
    end
    

    The code above it just an example with minimal adaption of your code.