diff --git a/src/aws_credentials_ec2.erl b/src/aws_credentials_ec2.erl
index 5796c85..5601752 100644
--- a/src/aws_credentials_ec2.erl
+++ b/src/aws_credentials_ec2.erl
@@ -31,7 +31,7 @@
-export([fetch/1]).
--spec fetch(aws_credentials_provider:options()) ->
+-spec fetch(any()) ->
{error, _}
| {ok, aws_credentials:credentials(), aws_credentials_provider:expiration()}.
fetch(_Options) ->
diff --git a/src/aws_credentials_file.erl b/src/aws_credentials_file.erl
index dfc47d5..51a83c2 100644
--- a/src/aws_credentials_file.erl
+++ b/src/aws_credentials_file.erl
@@ -21,10 +21,11 @@
%%
%% Environment parameters:
%%
-%% - <<"credentials_path">> - this is the base path to the both CLI configuration files.
+%%
- 'credential_path' - this is the base path to the both CLI configuration files.
%% And based on this path, credentials file should exist and config file is optional.
-%% By default this is `~/.aws/'
-%% - <<"profile">> - this is the desired profile to use in the credentials file.
+%% By default this is "~/.aws/"
+%% - 'profile'; - this is the desired profile to use in the credentials file.
+%% The profile can also be provided via the "AWS_PROFILE" os env.
%% By default this is <<"default">>
%%
%% @end
@@ -33,7 +34,12 @@
-export([fetch/1]).
--spec fetch(aws_credentials_provider:options()) ->
+-type options() :: #{ credential_path => string()
+ , profile => binary()
+ }.
+-export_type([options/0]).
+
+-spec fetch(options()) ->
{error, any()} | {ok, aws_credentials:credentials(), 'infinity'}.
fetch(Options) ->
FilePath = get_file_path(Options),
@@ -62,7 +68,7 @@ maybe_path_from_env(EnvVar, FilePath) ->
{_, Path} -> Path
end.
--spec get_file_path(aws_credentials_provider:options()) -> {error, any()} | string().
+-spec get_file_path(options()) -> {error, any()} | string().
get_file_path(Options) ->
case maps:get(credential_path, Options, undefined) of
undefined -> maybe_add_home("/.aws/");
@@ -79,7 +85,7 @@ maybe_add_home(Path) ->
-spec maybe_add_region(
{error, any()} | {ok, aws_credentials:credentials(), 'infinity'},
{error, any()} | string(),
- aws_credentials_provider:options()
+ options()
) -> {ok, aws_credentials:credentials(), 'infinity'}.
maybe_add_region({error, _} = Error, _Config, _Options) -> Error;
maybe_add_region(Result, {error, _Error}, _Options) -> Result;
@@ -98,7 +104,7 @@ check_path_exists(Path) ->
true -> Path
end.
--spec parse_credentials_file(string(), aws_credentials_provider:options()) ->
+-spec parse_credentials_file(string(), options()) ->
{error, any()} | {ok, aws_credentials:credentials(), 'infinity'}.
parse_credentials_file(Path, Options) ->
{ok, F} = file:read_file(Path),
@@ -123,7 +129,7 @@ parse_credentials_file(Path, Options) ->
end
end.
--spec parse_config_file(string(), aws_credentials_provider:options()) ->
+-spec parse_config_file(string(), options()) ->
{error, any()} | {ok, map()}.
parse_config_file(Path, Options) ->
{ok, F} = file:read_file(Path),
@@ -138,7 +144,7 @@ read_from_profile(File, Profile) ->
Map -> {ok, Map}
end.
--spec desired_profile(aws_credentials_provider:options()) -> binary().
+-spec desired_profile(options()) -> binary().
desired_profile(Options) ->
case {os:getenv("AWS_PROFILE"), maps:get(profile, Options, undefined)} of
{false, undefined} -> <<"default">>;
diff --git a/src/aws_credentials_provider.erl b/src/aws_credentials_provider.erl
index 9ea7430..37867dc 100644
--- a/src/aws_credentials_provider.erl
+++ b/src/aws_credentials_provider.erl
@@ -30,7 +30,19 @@
-export([fetch/0, fetch/1]).
--type options() :: #{provider() => map()}.
+%% `credential_path' and `profile' are treated as common options,
+%% and their values are inherited by `provider_specific_options()'
+%% unless the same options exist in `provider_specific_options()'.
+%% Note: This behaviour is for compatibility reason only, and
+%% do not add any further common options.
+-type options() :: #{ credential_path => string()
+ , profile => binary()
+ , provider() => provider_specific_options()
+ }.
+-type provider_specific_options() :: #{ credential_path => string()
+ , profile => binary()
+ , any() => any()
+ }.
-type expiration() :: binary() | pos_integer() | infinity.
-type provider() :: aws_credentials_env
| aws_credentials_file
@@ -40,7 +52,7 @@
-type error_log() :: [{provider(), term()}].
-export_type([ options/0, expiration/0, provider/0 ]).
--callback fetch(options()) ->
+-callback fetch(provider_specific_options()) ->
{ok, aws_credentials:credentials(), expiration()} | {error, any()}.
-include_lib("kernel/include/logger.hrl").
@@ -74,7 +86,8 @@ evaluate_providers([], _Options, []) ->
evaluate_providers([], _Options, Errors) when is_list(Errors) ->
{error, lists:reverse(Errors)};
evaluate_providers([ Provider | Providers ], Options, Errors) ->
- case Provider:fetch(Options) of
+ ProviderOptions = get_provider_specific_options(Provider, Options),
+ case Provider:fetch(ProviderOptions) of
{error, _} = Error ->
evaluate_providers(Providers, Options, [{Provider, Error} | Errors]);
{ok, Credentials, Expiration} ->
@@ -87,3 +100,12 @@ get_env(Key, Default) ->
undefined -> Default;
{ok, Value} -> Value
end.
+
+-spec get_provider_specific_options(provider(), options()) -> provider_specific_options().
+get_provider_specific_options(Provider, Options) ->
+ ProviderSpecificOptions = maps:get(Provider, Options, #{}),
+ IsCommonOptions = fun(profile, _) -> true; (credential_path, _) -> true; (_, _) -> false end,
+ CommonOptions = maps:filter(IsCommonOptions, Options),
+ %% If an option exists in both ProviderSpecificOptions and CommonOptions,
+ %% the value in ProviderSpecificOptions should be adopted.
+ maps:merge(CommonOptions, ProviderSpecificOptions).