@santana The purpose of supporting a path is to allow the instance profile credentials to be loaded in environments where a/the home directory is not available for the current user, but the file is available on disk.
Wouldn’t the following work?
Aws::InstanceProfileCredentials.new.each_profile do |profile_name, credentials|
# yielded creds are Aws::Credentials
end
Hey everyone. I’m attempting to get a stubbed Aws::AssumeRoleCredentials
instance with the following
aws_sts_client = Aws::STS::Client.new( credentials: credentials,
region: DEFAULT_AWS_REGION)
Aws::AssumeRoleCredentials.new( client: aws_sts_client,
role_arn: profile[:role_arn],
role_session_name: "#{profile[:name]}-session",
duration_seconds: DEFAULT_AWS_TOKEN_DURATION)
credentials
is either an instance of Aws::SharedCredentials
or Aws::Credentials
My issue is I keep seeing this error:
NoMethodError:
undefined method `access_key_id' for nil:NilClass
# /Users/brkattk/.rbenv/versions/2.2.2/gemsets/project-name/gems/aws-sdk-core-2.0.37/lib/aws-sdk-core/assume_role_credentials.rb:39:in `refresh'
# /Users/brkattk/.rbenv/versions/2.2.2/gemsets/project-name/gems/aws-sdk-core-2.0.37/lib/aws-sdk-core/refreshing_credentials.rb:20:in `initialize'
# /Users/brkattk/.rbenv/versions/2.2.2/gemsets/project-name/gems/aws-sdk-core-2.0.37/lib/aws-sdk-core/assume_role_credentials.rb:29:in `initialize'
# ./lib/project-name/configuration/aws_parser.rb:106:in `new'
# ./lib/project-name/configuration/aws_parser.rb:106:in `assume_role_credentials'
# ./lib/project-name/configuration/aws_parser.rb:83:in `build_credentials'
# ./lib/project-name/configuration/aws_parser.rb:63:in `block in validate_profiles'
# ./lib/project-name/configuration/aws_parser.rb:60:in `each'
# ./lib/project-name/configuration/aws_parser.rb:60:in `validate_profiles'
# ./lib/project-name/configuration/aws_parser.rb:49:in `validate!'
# ./lib/project-name/configuration/aws_parser.rb:29:in `parse!'
# ./spec/lib/project-name/configuration/aws_parser_spec.rb:186:in `block (9 levels) in <top (required)>'
# ./spec/lib/project-name/configuration/aws_parser_spec.rb:189:in `block (9 levels) in <top (required)>'
Aws.config[:stub_responses] = true
does not construct the actual responses you need, just simply stops the HTTP call from happening, right?
resp = aws_sts_client.assume_role(
role_arn: profile[:role_arn],
role_session_name: "#{profile[:name]}-session",
duration_seconds: DEFAULT_AWS_TOKEN_DURATION)
resp.context.http_response.status_code
resp.context.http_response.headers
resp.context.http_response.body_contents
I have an app that uses multiple different AWS credentials to do various things and eventually upload a file to S3. I’ve got an array of environments
like so
[
{
:name=>"default”,
:bucket_name=>”my.bucket”,
:bucket_region=>”us-east-1”,
:credentials=>#<Aws::SharedCredentials profile_name="default" path="/Users/brkattk/.aws/credentials”>
},
{
:name=>”secondary",
:bucket_name=>”my.bucket”,
:bucket_region=>”us-east-1”,
:credentials=>#<Aws::SharedCredentials profile_name=“secondary" path="/Users/brkattk/.aws/credentials”>
}
]
I’ve got a Report class that will upload a CSV to an environment’s designated bucket:
class Report
att_reader :csv, :environment
def initialize(environment, csv)
@environment = environment
@csv = csv
end
def upload!
s3_bucket.put_object(
body: csv.to_csv,
key: csv.to_filename,
content_type: 'text/csv')
end
private
def s3_resource
::Aws::S3::Resource.new(client: s3_client)
end
def s3_bucket
s3_resource.bucket environment[:bucket_name]
end
def s3_client
::Aws::S3::Client.new(credentials: environment[:credentials], region: environment[:bucket_region])
end
end
I’m looping each environment and producing a report, however, it is uploading both files to the last environment’s bucket.
Am I going insane?
S3::Object.new(bucket_name, key).put(body:’…’, content_type: ‘…')
my.bucket
I have 2 profiles in my ~/.aws/credentials
that are completely separate AWS accounts (one is my personal, one for my company)
I created an ran this script. I do not have a bucket named reports
in my personal AWS account, but this puts the first object in my company account’s report
bucket
require 'rubygems'
require 'aws-sdk'
creds1 = Aws::SharedCredentials.new(profile_name: 'erik')
s3_client1 = Aws::S3::Client.new(region: 'us-east-1', credentials: creds1)
s3_resource1 = Aws::S3::Resource.new(client: s3_client1)
s3_bucket1 = s3_resource1.bucket('reports')
object = s3_bucket1.objects.first
p object
instance = Aws::EC2::Resource.new.instances.first
old_timestamp = instance.password_data.timestamp
instance.reboot
instance.wait_until { |i| i.password_data.timestamp != old_timestamp }
response
in the block was nil on at least the first attempt, which seemed odd
... do |attempts, response|
puts "#{attempts}; timestamp this time: #{response.password_data.timestamp}"
end
nil
proc = Proc.new do |attempts, response|
logger.debug "Waiting for password data timestamp to be newer", {pwd_timestamp: instance.password_data.timestamp, newer_than: since}
end
instance.wait_until(max_attempts: 30, delay: 10, before_wait: proc) { |i| i.password_data.timestamp != since }
i
is an Instance resource
w.max_attempts = 15
w.interval = 0
w.before_attempt do |a, resp|
pause_exponentially n
logger.debug "Waiting for password...", {instance_id: id, attempt_count: a}
end
def pause_exponentially(n, seed=2, exp=1.4)
sleep(seed * (exp ** n))
end
There is not an accessible way to change the default waiter value currently. Currently, the waiter provider is a private interface, and is subject to change. If you are comfortable poking into something that may change in the future, you could do the following:
EC2::Client.waiters.instance_variable_get("@waiters")[:instance_running][:delay] = 20
I’d be open to suggestions on how to make this more flexible, until then, I left the interfaces marked @api private.