diff --git a/README.md b/README.md index 9c680160..e44e71c1 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,13 @@ this file in your knife.rb file, like so: knife[:aws_credential_file] = "/path/to/credentials/file/in/above/format" ``` +If you have multiple profiles in your credentials file you can define which +profile to use. The `default` profile will be used if not supplied, + +```ruby +knife[:aws_profile] = "personal" +``` + Additionally the following options may be set in your `knife.rb`: - flavor diff --git a/lib/chef/knife/ec2_base.rb b/lib/chef/knife/ec2_base.rb index 65841874..6141cf95 100644 --- a/lib/chef/knife/ec2_base.rb +++ b/lib/chef/knife/ec2_base.rb @@ -39,6 +39,12 @@ def self.included(includer) :description => "File containing AWS credentials as used by aws cmdline tools", :proc => Proc.new { |key| Chef::Config[:knife][:aws_credential_file] = key } + option :aws_profile, + :long => "--aws-profile PROFILE", + :description => "AWS profile, from credential file, to use", + :default => 'default', + :proc => Proc.new { |key| Chef::Config[:knife][:aws_profile] = key } + option :aws_access_key_id, :short => "-A ID", :long => "--aws-access-key-id KEY", @@ -115,14 +121,14 @@ def validate!(keys=[:aws_access_key_id, :aws_secret_access_key]) # AWSAccessKeyId=somethingsomethingdarkside # AWSSecretKey=somethingsomethingcomplete # OR + # [default] # aws_access_key_id = somethingsomethingdarkside # aws_secret_access_key = somethingsomethingdarkside - aws_creds = [] - File.read(Chef::Config[:knife][:aws_credential_file]).each_line do | line | - aws_creds << line.split("=").map(&:strip) if line.include?("=") - end - entries = Hash[*aws_creds.flatten] + aws_creds = ini_parse(File.read(Chef::Config[:knife][:aws_credential_file])) + profile = Chef::Config[:knife][:aws_profile] || 'default' + entries = aws_creds.values.first.has_key?("AWSAccessKeyId") ? aws_creds.values.first : aws_creds[profile] + Chef::Config[:knife][:aws_access_key_id] = entries['AWSAccessKeyId'] || entries['aws_access_key_id'] Chef::Config[:knife][:aws_secret_access_key] = entries['AWSSecretKey'] || entries['aws_secret_access_key'] end @@ -149,5 +155,24 @@ def iam_name_from_profile(profile) end name ||= '' end + + def ini_parse(file) + current_section = {} + map = {} + file.each_line do |line| + line = line.split(/^|\s;/).first # remove comments + section = line.match(/^\s*\[([^\[\]]+)\]\s*$/) unless line.nil? + if section + current_section = section[1] + elsif current_section + item = line.match(/^\s*(.+?)\s*=\s*(.+?)\s*$/) unless line.nil? + if item + map[current_section] ||= {} + map[current_section][item[1]] = item[2] + end + end + end + map + end end end diff --git a/spec/unit/ec2_server_create_spec.rb b/spec/unit/ec2_server_create_spec.rb index 697643c9..7599b53c 100644 --- a/spec/unit/ec2_server_create_spec.rb +++ b/spec/unit/ec2_server_create_spec.rb @@ -704,7 +704,7 @@ end it "reads UNIX Line endings for new format" do allow(File).to receive(:read). - and_return("aws_access_key_id=#{@access_key_id}\naws_secret_access_key=#{@secret_key}") + and_return("[default]\naws_access_key_id=#{@access_key_id}\naws_secret_access_key=#{@secret_key}") @knife_ec2_create.validate! expect(Chef::Config[:knife][:aws_access_key_id]).to eq(@access_key_id) expect(Chef::Config[:knife][:aws_secret_access_key]).to eq(@secret_key) @@ -712,11 +712,20 @@ it "reads DOS Line endings for new format" do allow(File).to receive(:read). - and_return("aws_access_key_id=#{@access_key_id}\r\naws_secret_access_key=#{@secret_key}") + and_return("[default]\naws_access_key_id=#{@access_key_id}\r\naws_secret_access_key=#{@secret_key}") @knife_ec2_create.validate! expect(Chef::Config[:knife][:aws_access_key_id]).to eq(@access_key_id) expect(Chef::Config[:knife][:aws_secret_access_key]).to eq(@secret_key) - end + end + + it "loads the correct profile" do + Chef::Config[:knife][:aws_profile] = 'other' + allow(File).to receive(:read). + and_return("[default]\naws_access_key_id=TESTKEY\r\naws_secret_access_key=TESTSECRET\n\n[other]\naws_access_key_id=#{@access_key_id}\r\naws_secret_access_key=#{@secret_key}") + @knife_ec2_create.validate! + expect(Chef::Config[:knife][:aws_access_key_id]).to eq(@access_key_id) + expect(Chef::Config[:knife][:aws_secret_access_key]).to eq(@secret_key) + end end it 'understands that file:// validation key URIs are just paths' do