Packages

Runtime core for the aws-gleam SDK: credentials, SigV4 + SigV4a signing, endpoint resolution, retry, HTTP transport, waiters, paginators, and Smithy protocol codecs.

Current section

Files

Jump to
aws_gleam_runtime src aws@internal@providers@ecs.erl
Raw

src/aws@internal@providers@ecs.erl

-module(aws@internal@providers@ecs).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/aws/internal/providers/ecs.gleam").
-export([fetch/2]).
-export_type([options/0, ecs_credentials/0, error/0, raw_credentials/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" ECS container credentials provider.\n"
"\n"
" One HTTP GET to a URL the container runtime advertises in environment\n"
" variables — typically `http://169.254.170.2<relative-uri>` inside an\n"
" ECS/EKS task. Response shape is the same as IMDS step 3 (a JSON\n"
" document with `AccessKeyId`, `SecretAccessKey`, `Token`, `Expiration`).\n"
"\n"
" Auth token, when present, goes in the `Authorization` header verbatim.\n"
" AWS Fargate gates the metadata endpoint with this token, so an empty\n"
" value means \"no auth header at all\" (None) rather than \"send the empty\n"
" string\".\n"
).
-type options() :: {options, binary(), gleam@option:option(binary())}.
-type ecs_credentials() :: {ecs_credentials,
binary(),
binary(),
gleam@option:option(binary()),
gleam@option:option(integer())}.
-type error() :: {unreachable, binary()} | {failed, binary()}.
-type raw_credentials() :: {raw_credentials,
binary(),
binary(),
gleam@option:option(binary()),
gleam@option:option(binary())}.
-file("src/aws/internal/providers/ecs.gleam", 117).
-spec raw_decoder() -> gleam@dynamic@decode:decoder(raw_credentials()).
raw_decoder() ->
gleam@dynamic@decode:field(
<<"AccessKeyId"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Access_key_id) ->
gleam@dynamic@decode:field(
<<"SecretAccessKey"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Secret_access_key) ->
gleam@dynamic@decode:then(
gleam@dynamic@decode:optionally_at(
[<<"Token"/utf8>>],
none,
gleam@dynamic@decode:map(
{decoder,
fun gleam@dynamic@decode:decode_string/1},
fun(Field@0) -> {some, Field@0} end
)
),
fun(Token) ->
gleam@dynamic@decode:then(
gleam@dynamic@decode:optionally_at(
[<<"Expiration"/utf8>>],
none,
gleam@dynamic@decode:map(
{decoder,
fun gleam@dynamic@decode:decode_string/1},
fun(Field@0) -> {some, Field@0} end
)
),
fun(Expiration) ->
gleam@dynamic@decode:success(
{raw_credentials,
Access_key_id,
Secret_access_key,
Token,
Expiration}
)
end
)
end
)
end
)
end
).
-file("src/aws/internal/providers/ecs.gleam", 138).
-spec decode_credentials(bitstring()) -> {ok, ecs_credentials()} |
{error, error()}.
decode_credentials(Body) ->
gleam@result:'try'(
begin
_pipe = gleam@bit_array:to_string(Body),
gleam@result:replace_error(
_pipe,
{failed, <<"non-utf8 credentials body"/utf8>>}
)
end,
fun(Text) ->
gleam@result:'try'(
begin
_pipe@1 = gleam@json:parse(Text, raw_decoder()),
gleam@result:map_error(
_pipe@1,
fun(_) ->
{failed,
<<"ECS response is not the expected JSON shape"/utf8>>}
end
)
end,
fun(Raw) ->
Expires_at = case erlang:element(5, Raw) of
{some, Ts} ->
case aws_ffi:parse_iso8601(Ts) of
{ok, T} ->
{some, T};
{error, _} ->
none
end;
none ->
none
end,
{ok,
{ecs_credentials,
erlang:element(2, Raw),
erlang:element(3, Raw),
erlang:element(4, Raw),
Expires_at}}
end
)
end
).
-file("src/aws/internal/providers/ecs.gleam", 97).
-spec describe_http(aws@internal@http_send:http_error()) -> binary().
describe_http(Error) ->
case Error of
{connect_failed, Reason} ->
<<"connect failed: "/utf8, Reason/binary>>;
timeout ->
<<"timeout"/utf8>>;
{invalid_body, Reason@1} ->
<<"invalid body: "/utf8, Reason@1/binary>>;
{other, Reason@2} ->
Reason@2
end.
-file("src/aws/internal/providers/ecs.gleam", 64).
-spec auth_headers(gleam@option:option(binary())) -> list({binary(), binary()}).
auth_headers(Token) ->
case Token of
{some, T} ->
[{<<"authorization"/utf8>>, T}];
none ->
[]
end.
-file("src/aws/internal/providers/ecs.gleam", 87).
-spec apply_headers(
gleam@http@request:request(bitstring()),
list({binary(), binary()})
) -> gleam@http@request:request(bitstring()).
apply_headers(Req, Headers) ->
case Headers of
[] ->
Req;
[{K, V} | Rest] ->
apply_headers(gleam@http@request:set_header(Req, K, V), Rest)
end.
-file("src/aws/internal/providers/ecs.gleam", 71).
-spec build_request(gleam@http:method(), binary(), list({binary(), binary()})) -> {ok,
gleam@http@request:request(bitstring())} |
{error, binary()}.
build_request(Method, Url, Headers) ->
gleam@result:'try'(
begin
_pipe = gleam@http@request:to(Url),
gleam@result:replace_error(
_pipe,
<<"invalid URL: "/utf8, Url/binary>>
)
end,
fun(Base) ->
Req = begin
_pipe@1 = Base,
_pipe@2 = gleam@http@request:set_method(_pipe@1, Method),
gleam@http@request:set_body(
_pipe@2,
gleam_stdlib:identity(<<""/utf8>>)
)
end,
{ok, apply_headers(Req, Headers)}
end
).
-file("src/aws/internal/providers/ecs.gleam", 44).
-spec fetch(
fun((gleam@http@request:request(bitstring())) -> {ok,
gleam@http@response:response(bitstring())} |
{error, aws@internal@http_send:http_error()}),
options()
) -> {ok, ecs_credentials()} | {error, error()}.
fetch(Send, Options) ->
gleam@result:'try'(
begin
_pipe = build_request(
get,
erlang:element(2, Options),
auth_headers(erlang:element(3, Options))
),
gleam@result:map_error(_pipe, fun(Reason) -> {failed, Reason} end)
end,
fun(Req) ->
gleam@result:'try'(
begin
_pipe@1 = Send(Req),
gleam@result:map_error(
_pipe@1,
fun(E) ->
{unreachable,
<<"ECS metadata transport: "/utf8,
(describe_http(E))/binary>>}
end
)
end,
fun(Resp) -> case erlang:element(2, Resp) of
200 ->
decode_credentials(erlang:element(4, Resp));
Other ->
{error,
{failed,
<<"ECS metadata returned status "/utf8,
(erlang:integer_to_binary(Other))/binary>>}}
end end
)
end
).