Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 32 additions & 18 deletions lib/aws/client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,16 @@ defmodule AWS.Client do
Check `put_endpoint/2` for more details.
"""
@type endpoint_config :: binary() | {:keep_prefixes, binary()} | (map() -> binary()) | nil
@type access_key_id :: binary()
@type secret_access_key :: binary()
@type token :: binary() | nil
@type region :: binary()

@type t :: %__MODULE__{
access_key_id: binary() | nil,
secret_access_key: binary() | nil,
session_token: binary() | nil,
region: binary() | nil,
access_key_id: access_key_id() | nil,
secret_access_key: secret_access_key() | nil,
session_token: token() | nil,
region: region() | nil,
service: binary() | nil,
endpoint: endpoint_config(),
proto: binary(),
Expand All @@ -72,6 +76,7 @@ defmodule AWS.Client do
@aws_access_key_id "AWS_ACCESS_KEY_ID"
@aws_secret_access_key "AWS_SECRET_ACCESS_KEY"
@aws_session_token "AWS_SESSION_TOKEN"
@aws_endpoint "AWS_ENDPOINT"
@aws_default_region "AWS_DEFAULT_REGION"

@doc """
Expand All @@ -82,6 +87,17 @@ defmodule AWS.Client do
"""
def default_endpoint, do: @aws_default_endpoint

@spec create() :: t()
@spec create(region()) :: t()
@spec create(access_key_id(), secret_access_key(), region()) :: t()
@spec create(access_key_id(), secret_access_key(), token(), region()) :: t()
@spec create(
access_key_id(),
secret_access_key(),
token() | nil,
region(),
endpoint_config() | nil
) :: t()
def create() do
case System.get_env(@aws_default_region) do
nil -> raise RuntimeError, "missing default region"
Expand All @@ -91,35 +107,33 @@ defmodule AWS.Client do

def create(region) do
case {System.get_env(@aws_access_key_id), System.get_env(@aws_secret_access_key),
System.get_env(@aws_session_token)} do
{nil, _, _} ->
System.get_env(@aws_session_token), System.get_env(@aws_endpoint)} do
{nil, _secret_key, _session_token, _endpoint} ->
raise RuntimeError, "missing access key id"

{_, nil, _} ->
{_access_key, nil, _session_token, _endpoint} ->
raise RuntimeError, "missing secret access key"

{access_key_id, secret_access_key, nil} ->
create(access_key_id, secret_access_key, region)

{access_key_id, secret_access_key, token} ->
create(access_key_id, secret_access_key, token, region)
{access_key_id, secret_access_key, token, endpoint} ->
create(access_key_id, secret_access_key, token, region, endpoint)
end
end

def create(access_key_id, secret_access_key, region) do
%AWS.Client{
access_key_id: access_key_id,
secret_access_key: secret_access_key,
region: region
}
create(access_key_id, secret_access_key, nil, region, nil)
end

def create(access_key_id, secret_access_key, token, region) do
Comment on lines 122 to 126
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving the previous API, so no breaking changes are made.

create(access_key_id, secret_access_key, token, region, nil)
end

def create(access_key_id, secret_access_key, token, region, endpoint) do
%AWS.Client{
access_key_id: access_key_id,
secret_access_key: secret_access_key,
session_token: token,
region: region
region: region,
endpoint: endpoint
}
end

Expand Down
135 changes: 135 additions & 0 deletions test/aws/client_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -122,5 +122,140 @@ defmodule AWS.ClientTest do
end
end

describe "create/n" do
setup :prune_envs

test "create/0 reads region from AWS_DEFAULT_REGION and builds client" do
System.put_env("AWS_ACCESS_KEY_ID", "AK")
System.put_env("AWS_SECRET_ACCESS_KEY", "SK")
System.put_env("AWS_DEFAULT_REGION", "us-east-1")

client = AWS.Client.create()

assert %AWS.Client{
access_key_id: "AK",
secret_access_key: "SK",
session_token: nil,
region: "us-east-1",
endpoint: nil
} == client
end

test "create/0 raises when AWS_DEFAULT_REGION missing" do
System.put_env("AWS_ACCESS_KEY_ID", "AK")
System.put_env("AWS_SECRET_ACCESS_KEY", "SK")

assert_raise RuntimeError, "missing default region", fn ->
AWS.Client.create()
end
end

test "create/1 reads credentials, token and endpoint from env" do
System.put_env("AWS_ACCESS_KEY_ID", "AK")
System.put_env("AWS_SECRET_ACCESS_KEY", "SK")
System.put_env("AWS_SESSION_TOKEN", "TOK")
System.put_env("AWS_ENDPOINT", "example.com")

client = AWS.Client.create("us-west-2")

assert %AWS.Client{
access_key_id: "AK",
secret_access_key: "SK",
session_token: "TOK",
region: "us-west-2",
endpoint: "example.com"
} == client
end

test "create/1 without token uses nil and endpoint from env" do
System.put_env("AWS_ACCESS_KEY_ID", "AK")
System.put_env("AWS_SECRET_ACCESS_KEY", "SK")
System.put_env("AWS_ENDPOINT", "example.com")

client = AWS.Client.create("eu-west-1")

assert %AWS.Client{
access_key_id: "AK",
secret_access_key: "SK",
session_token: nil,
region: "eu-west-1",
endpoint: "example.com"
} == client
end

test "create/1 raises when access key is missing" do
System.put_env("AWS_SECRET_ACCESS_KEY", "SK")

assert_raise RuntimeError, "missing access key id", fn ->
AWS.Client.create("us-east-2")
end
end

test "create/1 raises when secret access key is missing" do
System.put_env("AWS_ACCESS_KEY_ID", "AK")

assert_raise RuntimeError, "missing secret access key", fn ->
AWS.Client.create("us-east-2")
end
end

test "create/3 sets fields without token or endpoint" do
client = AWS.Client.create("AK", "SK", "eu-north-1")

assert %AWS.Client{
access_key_id: "AK",
secret_access_key: "SK",
session_token: nil,
region: "eu-north-1",
endpoint: nil
} == client
end

test "create/4 sets token and leaves endpoint nil" do
client = AWS.Client.create("AK", "SK", "TOKEN", "ap-south-1")

assert %AWS.Client{
access_key_id: "AK",
secret_access_key: "SK",
session_token: "TOKEN",
region: "ap-south-1",
endpoint: nil
} == client
end

test "create/5 sets token and endpoint" do
client = AWS.Client.create("AK", "SK", "TOKEN", "sa-east-1", "custom.local")

assert %AWS.Client{
access_key_id: "AK",
secret_access_key: "SK",
session_token: "TOKEN",
region: "sa-east-1",
endpoint: "custom.local"
} == client
end

test "create/3 equals create/5 with nil token and endpoint" do
c3 = AWS.Client.create("AK", "SK", "us-east-1")
c5 = AWS.Client.create("AK", "SK", nil, "us-east-1", nil)
assert c3 == c5
end
end

defp prune_envs(_context) do
keys =
[
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY",
"AWS_SESSION_TOKEN",
"AWS_ENDPOINT",
"AWS_DEFAULT_REGION"
]

on_exit(fn -> Enum.each(keys, &System.delete_env/1) end)

:ok
end

defp url(bypass), do: "http://localhost:#{bypass.port}/"
end
Loading