{"action":"created","comment":{"url":"https://api.github.com/repos/rusoto/rusoto/pulls/comments/82919791","pull_request_review_id":3793103,"id":82919791,"diff_hunk":"@@ -306,7 +355,309 @@ fn parse_credentials_file(file_path: &Path) -> Result<HashMap<String, AwsCredent\n     Ok(profiles)\n }\n \n+pub trait LoadFromPath where Self: Sized {\n+    type Error: Sized + 'static;\n+\n+    fn load_from_path(filename: &Path) -> Result<Self, Self::Error>;\n+}\n+\n+impl LoadFromPath for Ini {\n+    type Error = ini::Error;\n+\n+    fn load_from_path(filename: &Path) -> Result<Ini, Self::Error> {\n+        let mut reader = match File::open(filename) {\n+            Err(e) => {\n+                return Err(ini::Error {\n+                    line: 0,\n+                    col: 0,\n+                    msg: format!(\"Unable to open `{:?}`: {}\", filename, e),\n+                })\n+            }\n+            Ok(r) => r,\n+        };\n+        Ini::read_from(&mut reader)\n+    }\n+}\n+\n+#[derive(Debug, Clone)]\n+pub struct ConfigProfile {\n+    pub name: String,\n+    pub role_arn: Option<String>,\n+    pub source_profile: Option<String>,\n+    pub region: Option<region::Region>,\n+}\n+\n+impl ConfigProfile {\n+    pub fn new<S>(name: S) -> ConfigProfile where S: Into<String> {\n+        ConfigProfile {\n+            name: name.into(),\n+            role_arn: None,\n+            source_profile: None,\n+            region: None,\n+        }\n+    }\n+}\n+\n+#[derive(Debug, Clone)]\n+pub struct Config {\n+    pub default_region: Option<region::Region>,\n+    pub profiles: HashMap<String, ConfigProfile>,\n+}\n+\n+fn get_profile_name_from_section_name(section_name: &str) -> Option<String> {\n+    let prefix = \"profile \";\n+    if section_name.starts_with(prefix) {\n+        Some(section_name.chars().skip(prefix.len()).collect())\n+    } else {\n+        None\n+    }\n+}\n+\n+fn parse_config_file(file_path: &Path) -> Result<Config, CredentialsError> {\n+    let ini = try!(Ini::load_from_path(file_path));\n+\n+    let default_section = ini.section(Some(\"default\".to_owned()));\n+    let maybe_default_region_name = default_section.and_then(|s| s.get(\"region\"));\n+    let default_region = if let Some(default_region_name) = maybe_default_region_name {\n+        Some(try!(region::Region::from_str(default_region_name)))\n+    } else {\n+        None\n+    };\n+\n+    let mut profiles = HashMap::new();\n+\n+    for key in ini.sections() {\n+        if let Some(section_name) = key.as_ref() {  \n+            let section = ini.section(key.to_owned()).unwrap();\n+\n+            if let Some(profile_name) = get_profile_name_from_section_name(section_name) {\n+                let maybe_region_name = section.get(\"region\");\n+                let region = if let Some(region_name) = maybe_region_name {\n+                    Some(try!(region::Region::from_str(region_name)))\n+                } else {\n+                    None\n+                };\n+                let source_profile = section.get(\"source_profile\").map(|s| s.to_owned());\n+                let role_arn = section.get(\"role_arn\").map(|s| s.to_owned());\n+\n+                profiles.insert(profile_name.clone(), ConfigProfile {\n+                    name: profile_name,\n+                    role_arn: role_arn,\n+                    source_profile: source_profile,\n+                    region: region,\n+                });\n+            }\n+        }\n+    }\n+\n+    Ok(Config {\n+        default_region: default_region,\n+        profiles: profiles,\n+    })\n+}\n+\n+#[cfg(feature = \"sts\")]\n+mod sts {","path":"src/credential.rs","position":274,"original_position":274,"commit_id":"0e36f8971f1527a6cc5dcfe275a10b54fab7b9ac","original_commit_id":"0e36f8971f1527a6cc5dcfe275a10b54fab7b9ac","user":{"login":"matthewkmayer","id":4998189,"avatar_url":"https://avatars.githubusercontent.com/u/4998189?v=3","gravatar_id":"","url":"https://api.github.com/users/matthewkmayer","html_url":"https://github.com/matthewkmayer","followers_url":"https://api.github.com/users/matthewkmayer/followers","following_url":"https://api.github.com/users/matthewkmayer/following{/other_user}","gists_url":"https://api.github.com/users/matthewkmayer/gists{/gist_id}","starred_url":"https://api.github.com/users/matthewkmayer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/matthewkmayer/subscriptions","organizations_url":"https://api.github.com/users/matthewkmayer/orgs","repos_url":"https://api.github.com/users/matthewkmayer/repos","events_url":"https://api.github.com/users/matthewkmayer/events{/privacy}","received_events_url":"https://api.github.com/users/matthewkmayer/received_events","type":"User","site_admin":false},"body":"This `credentials.rs` file is getting a bit big.  This area seems like a good place to split into its own file if possible.","created_at":"2016-10-12T01:00:16Z","updated_at":"2016-10-12T01:00:16Z","html_url":"https://github.com/rusoto/rusoto/pull/367#discussion_r82919791","pull_request_url":"https://api.github.com/repos/rusoto/rusoto/pulls/367","_links":{"self":{"href":"https://api.github.com/repos/rusoto/rusoto/pulls/comments/82919791"},"html":{"href":"https://github.com/rusoto/rusoto/pull/367#discussion_r82919791"},"pull_request":{"href":"https://api.github.com/repos/rusoto/rusoto/pulls/367"}}},"pull_request":{"url":"https://api.github.com/repos/rusoto/rusoto/pulls/367","id":84041239,"html_url":"https://github.com/rusoto/rusoto/pull/367","diff_url":"https://github.com/rusoto/rusoto/pull/367.diff","patch_url":"https://github.com/rusoto/rusoto/pull/367.patch","issue_url":"https://api.github.com/repos/rusoto/rusoto/issues/367","number":367,"state":"open","locked":false,"title":"Add Sts credentials provider","user":{"login":"cmsd2","id":210833,"avatar_url":"https://avatars.githubusercontent.com/u/210833?v=3","gravatar_id":"","url":"https://api.github.com/users/cmsd2","html_url":"https://github.com/cmsd2","followers_url":"https://api.github.com/users/cmsd2/followers","following_url":"https://api.github.com/users/cmsd2/following{/other_user}","gists_url":"https://api.github.com/users/cmsd2/gists{/gist_id}","starred_url":"https://api.github.com/users/cmsd2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cmsd2/subscriptions","organizations_url":"https://api.github.com/users/cmsd2/orgs","repos_url":"https://api.github.com/users/cmsd2/repos","events_url":"https://api.github.com/users/cmsd2/events{/privacy}","received_events_url":"https://api.github.com/users/cmsd2/received_events","type":"User","site_admin":false},"body":"fyi This is blocked waiting on IAM support to be merged in.\r\n\r\nI've added a credentials provider that uses the STS to acquire session tokens possibly using a role arn.\r\n\r\nExample usage here: [https://github.com/cmsd2/stscli](https://github.com/cmsd2/stscli)\r\n\r\nI also found I had to modify the request signing to use a stricter percent encoding for the canonical query string.","created_at":"2016-09-05T21:50:15Z","updated_at":"2016-10-12T01:02:21Z","closed_at":null,"merged_at":null,"merge_commit_sha":"39d7a6177165dbe0565beb03d3e731dff29be397","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/rusoto/rusoto/pulls/367/commits","review_comments_url":"https://api.github.com/repos/rusoto/rusoto/pulls/367/comments","review_comment_url":"https://api.github.com/repos/rusoto/rusoto/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rusoto/rusoto/issues/367/comments","statuses_url":"https://api.github.com/repos/rusoto/rusoto/statuses/0e36f8971f1527a6cc5dcfe275a10b54fab7b9ac","head":{"label":"cmsd2:stsprovider","ref":"stsprovider","sha":"0e36f8971f1527a6cc5dcfe275a10b54fab7b9ac","user":{"login":"cmsd2","id":210833,"avatar_url":"https://avatars.githubusercontent.com/u/210833?v=3","gravatar_id":"","url":"https://api.github.com/users/cmsd2","html_url":"https://github.com/cmsd2","followers_url":"https://api.github.com/users/cmsd2/followers","following_url":"https://api.github.com/users/cmsd2/following{/other_user}","gists_url":"https://api.github.com/users/cmsd2/gists{/gist_id}","starred_url":"https://api.github.com/users/cmsd2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cmsd2/subscriptions","organizations_url":"https://api.github.com/users/cmsd2/orgs","repos_url":"https://api.github.com/users/cmsd2/repos","events_url":"https://api.github.com/users/cmsd2/events{/privacy}","received_events_url":"https://api.github.com/users/cmsd2/received_events","type":"User","site_admin":false},"repo":{"id":43752656,"name":"rusoto","full_name":"cmsd2/rusoto","owner":{"login":"cmsd2","id":210833,"avatar_url":"https://avatars.githubusercontent.com/u/210833?v=3","gravatar_id":"","url":"https://api.github.com/users/cmsd2","html_url":"https://github.com/cmsd2","followers_url":"https://api.github.com/users/cmsd2/followers","following_url":"https://api.github.com/users/cmsd2/following{/other_user}","gists_url":"https://api.github.com/users/cmsd2/gists{/gist_id}","starred_url":"https://api.github.com/users/cmsd2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cmsd2/subscriptions","organizations_url":"https://api.github.com/users/cmsd2/orgs","repos_url":"https://api.github.com/users/cmsd2/repos","events_url":"https://api.github.com/users/cmsd2/events{/privacy}","received_events_url":"https://api.github.com/users/cmsd2/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/cmsd2/rusoto","description":"AWS client libraries for Rust","fork":true,"url":"https://api.github.com/repos/cmsd2/rusoto","forks_url":"https://api.github.com/repos/cmsd2/rusoto/forks","keys_url":"https://api.github.com/repos/cmsd2/rusoto/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cmsd2/rusoto/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cmsd2/rusoto/teams","hooks_url":"https://api.github.com/repos/cmsd2/rusoto/hooks","issue_events_url":"https://api.github.com/repos/cmsd2/rusoto/issues/events{/number}","events_url":"https://api.github.com/repos/cmsd2/rusoto/events","assignees_url":"https://api.github.com/repos/cmsd2/rusoto/assignees{/user}","branches_url":"https://api.github.com/repos/cmsd2/rusoto/branches{/branch}","tags_url":"https://api.github.com/repos/cmsd2/rusoto/tags","blobs_url":"https://api.github.com/repos/cmsd2/rusoto/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cmsd2/rusoto/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cmsd2/rusoto/git/refs{/sha}","trees_url":"https://api.github.com/repos/cmsd2/rusoto/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cmsd2/rusoto/statuses/{sha}","languages_url":"https://api.github.com/repos/cmsd2/rusoto/languages","stargazers_url":"https://api.github.com/repos/cmsd2/rusoto/stargazers","contributors_url":"https://api.github.com/repos/cmsd2/rusoto/contributors","subscribers_url":"https://api.github.com/repos/cmsd2/rusoto/subscribers","subscription_url":"https://api.github.com/repos/cmsd2/rusoto/subscription","commits_url":"https://api.github.com/repos/cmsd2/rusoto/commits{/sha}","git_commits_url":"https://api.github.com/repos/cmsd2/rusoto/git/commits{/sha}","comments_url":"https://api.github.com/repos/cmsd2/rusoto/comments{/number}","issue_comment_url":"https://api.github.com/repos/cmsd2/rusoto/issues/comments{/number}","contents_url":"https://api.github.com/repos/cmsd2/rusoto/contents/{+path}","compare_url":"https://api.github.com/repos/cmsd2/rusoto/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cmsd2/rusoto/merges","archive_url":"https://api.github.com/repos/cmsd2/rusoto/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cmsd2/rusoto/downloads","issues_url":"https://api.github.com/repos/cmsd2/rusoto/issues{/number}","pulls_url":"https://api.github.com/repos/cmsd2/rusoto/pulls{/number}","milestones_url":"https://api.github.com/repos/cmsd2/rusoto/milestones{/number}","notifications_url":"https://api.github.com/repos/cmsd2/rusoto/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cmsd2/rusoto/labels{/name}","releases_url":"https://api.github.com/repos/cmsd2/rusoto/releases{/id}","deployments_url":"https://api.github.com/repos/cmsd2/rusoto/deployments","created_at":"2015-10-06T13:33:55Z","updated_at":"2015-10-06T13:33:56Z","pushed_at":"2016-10-08T21:14:53Z","git_url":"git://github.com/cmsd2/rusoto.git","ssh_url":"git@github.com:cmsd2/rusoto.git","clone_url":"https://github.com/cmsd2/rusoto.git","svn_url":"https://github.com/cmsd2/rusoto","homepage":null,"size":3451,"stargazers_count":0,"watchers_count":0,"language":"Rust","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"rusoto:master","ref":"master","sha":"29db65eb66531c66c641b27b2e124fad7fa055e5","user":{"login":"rusoto","id":15861923,"avatar_url":"https://avatars.githubusercontent.com/u/15861923?v=3","gravatar_id":"","url":"https://api.github.com/users/rusoto","html_url":"https://github.com/rusoto","followers_url":"https://api.github.com/users/rusoto/followers","following_url":"https://api.github.com/users/rusoto/following{/other_user}","gists_url":"https://api.github.com/users/rusoto/gists{/gist_id}","starred_url":"https://api.github.com/users/rusoto/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rusoto/subscriptions","organizations_url":"https://api.github.com/users/rusoto/orgs","repos_url":"https://api.github.com/users/rusoto/repos","events_url":"https://api.github.com/users/rusoto/events{/privacy}","received_events_url":"https://api.github.com/users/rusoto/received_events","type":"Organization","site_admin":false},"repo":{"id":39107211,"name":"rusoto","full_name":"rusoto/rusoto","owner":{"login":"rusoto","id":15861923,"avatar_url":"https://avatars.githubusercontent.com/u/15861923?v=3","gravatar_id":"","url":"https://api.github.com/users/rusoto","html_url":"https://github.com/rusoto","followers_url":"https://api.github.com/users/rusoto/followers","following_url":"https://api.github.com/users/rusoto/following{/other_user}","gists_url":"https://api.github.com/users/rusoto/gists{/gist_id}","starred_url":"https://api.github.com/users/rusoto/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rusoto/subscriptions","organizations_url":"https://api.github.com/users/rusoto/orgs","repos_url":"https://api.github.com/users/rusoto/repos","events_url":"https://api.github.com/users/rusoto/events{/privacy}","received_events_url":"https://api.github.com/users/rusoto/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rusoto/rusoto","description":"AWS SDK for Rust","fork":false,"url":"https://api.github.com/repos/rusoto/rusoto","forks_url":"https://api.github.com/repos/rusoto/rusoto/forks","keys_url":"https://api.github.com/repos/rusoto/rusoto/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rusoto/rusoto/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rusoto/rusoto/teams","hooks_url":"https://api.github.com/repos/rusoto/rusoto/hooks","issue_events_url":"https://api.github.com/repos/rusoto/rusoto/issues/events{/number}","events_url":"https://api.github.com/repos/rusoto/rusoto/events","assignees_url":"https://api.github.com/repos/rusoto/rusoto/assignees{/user}","branches_url":"https://api.github.com/repos/rusoto/rusoto/branches{/branch}","tags_url":"https://api.github.com/repos/rusoto/rusoto/tags","blobs_url":"https://api.github.com/repos/rusoto/rusoto/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rusoto/rusoto/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rusoto/rusoto/git/refs{/sha}","trees_url":"https://api.github.com/repos/rusoto/rusoto/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rusoto/rusoto/statuses/{sha}","languages_url":"https://api.github.com/repos/rusoto/rusoto/languages","stargazers_url":"https://api.github.com/repos/rusoto/rusoto/stargazers","contributors_url":"https://api.github.com/repos/rusoto/rusoto/contributors","subscribers_url":"https://api.github.com/repos/rusoto/rusoto/subscribers","subscription_url":"https://api.github.com/repos/rusoto/rusoto/subscription","commits_url":"https://api.github.com/repos/rusoto/rusoto/commits{/sha}","git_commits_url":"https://api.github.com/repos/rusoto/rusoto/git/commits{/sha}","comments_url":"https://api.github.com/repos/rusoto/rusoto/comments{/number}","issue_comment_url":"https://api.github.com/repos/rusoto/rusoto/issues/comments{/number}","contents_url":"https://api.github.com/repos/rusoto/rusoto/contents/{+path}","compare_url":"https://api.github.com/repos/rusoto/rusoto/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rusoto/rusoto/merges","archive_url":"https://api.github.com/repos/rusoto/rusoto/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rusoto/rusoto/downloads","issues_url":"https://api.github.com/repos/rusoto/rusoto/issues{/number}","pulls_url":"https://api.github.com/repos/rusoto/rusoto/pulls{/number}","milestones_url":"https://api.github.com/repos/rusoto/rusoto/milestones{/number}","notifications_url":"https://api.github.com/repos/rusoto/rusoto/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rusoto/rusoto/labels{/name}","releases_url":"https://api.github.com/repos/rusoto/rusoto/releases{/id}","deployments_url":"https://api.github.com/repos/rusoto/rusoto/deployments","created_at":"2015-07-15T00:22:17Z","updated_at":"2016-10-10T03:02:04Z","pushed_at":"2016-10-12T00:57:40Z","git_url":"git://github.com/rusoto/rusoto.git","ssh_url":"git@github.com:rusoto/rusoto.git","clone_url":"https://github.com/rusoto/rusoto.git","svn_url":"https://github.com/rusoto/rusoto","homepage":"","size":15350,"stargazers_count":186,"watchers_count":186,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":40,"mirror_url":null,"open_issues_count":28,"forks":40,"open_issues":28,"watchers":186,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rusoto/rusoto/pulls/367"},"html":{"href":"https://github.com/rusoto/rusoto/pull/367"},"issue":{"href":"https://api.github.com/repos/rusoto/rusoto/issues/367"},"comments":{"href":"https://api.github.com/repos/rusoto/rusoto/issues/367/comments"},"review_comments":{"href":"https://api.github.com/repos/rusoto/rusoto/pulls/367/comments"},"review_comment":{"href":"https://api.github.com/repos/rusoto/rusoto/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rusoto/rusoto/pulls/367/commits"},"statuses":{"href":"https://api.github.com/repos/rusoto/rusoto/statuses/0e36f8971f1527a6cc5dcfe275a10b54fab7b9ac"}}}}
{"actor":{"display_login":"matthewkmayer"}}