Skip to content

Commit 58b689b

Browse files
committed
Add rabbitmq_aws:api_post_request/4, README cleanup
1 parent c57a562 commit 58b689b

File tree

3 files changed

+74
-45
lines changed

3 files changed

+74
-45
lines changed

deps/rabbitmq_aws/README.md

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ A fork of [gmr/httpc-aws](https://github.com/gmr/httpc-aws) for use in building
55
## Supported Erlang Versions
66

77
[Same as RabbitMQ](http://www.rabbitmq.com/which-erlang.html)
8-
8+
99
## Configuration
1010

1111
Configuration for *rabbitmq-aws* is can be provided in multiple ways. It is designed
1212
to behave similarly to the [AWS Command Line Interface](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html)
1313
with respect to providing region and configuration information. Additionally it
14-
has two methods, ``rabbitmq_aws:set_region/1`` and ``rabbitmq_aws:set_credentials/2``
14+
has two methods, `rabbitmq_aws:set_region/1` and `rabbitmq_aws:set_credentials/2`
1515
to allow for application specific configuration, bypassing the automatic configuration
1616
behavior.
1717

@@ -40,36 +40,36 @@ and [adds defenses against additional vulnerabilities](https://aws.amazon.com/bl
4040
AWS recommends adopting IMDSv2 and disabling IMDSv1 [by configuring the Instance Metadata Service on the EC2 instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html).
4141

4242
By default *rabbitmq-aws* will attempt to use IMDSv2 first and will fallback to use IMDSv1 if calls to IMDSv2 fail. This behavior can be overridden
43-
by setting the ``aws.prefer_imdsv2`` setting to ``false``.
43+
by setting the `aws.prefer_imdsv2` setting to `false`.
4444

4545
### Environment Variables
4646

47-
As with the AWS CLI, the following environment variables can be used to provide
47+
As with the AWS CLI, the following environment variables can be used to provide
4848
configuration or to impact configuration behavior:
4949

50-
- ``AWS_DEFAULT_PROFILE``
51-
- ``AWS_DEFAULT_REGION``
52-
- ``AWS_CONFIG_FILE``
53-
- ``AWS_SHARED_CREDENTIALS_FILE``
54-
- ``AWS_ACCESS_KEY_ID``
55-
- ``AWS_SECRET_ACCESS_KEY``
56-
50+
- `AWS_DEFAULT_PROFILE`
51+
- `AWS_DEFAULT_REGION`
52+
- `AWS_CONFIG_FILE`
53+
- `AWS_SHARED_CREDENTIALS_FILE`
54+
- `AWS_ACCESS_KEY_ID`
55+
- `AWS_SECRET_ACCESS_KEY`
56+
5757
## API Functions
58-
59-
Method | Description
60-
---------------------------------------|--------------------------------------------------------------------------------------------
61-
``rabbitmq_aws:set_region/1`` | Manually specify the AWS region to make requests to.
62-
``rabbitmq_aws:set_credentials/2`` | Manually specify the request credentials to use.
63-
``rabbitmq_aws:refresh_credentials/0`` | Refresh the credentials from the environment, filesystem, or EC2 Instance Metadata Service.
64-
``rabbitmq_aws:ensure_imdsv2_token_valid/0`` | Make sure EC2 IMDSv2 token is active and valid.
65-
``rabbitmq_aws:api_get_request/2`` | Perform an AWS service API request.
66-
``rabbitmq_aws:get/2`` | Perform a GET request to the API specifying the service and request path.
67-
``rabbitmq_aws:get/3`` | Perform a GET request specifying the service, path, and headers.
68-
``rabbitmq_aws:post/4`` | Perform a POST request specifying the service, path, headers, and body.
69-
``rabbitmq_aws:request/5`` | Perform a request specifying the service, method, path, headers, and body.
70-
``rabbitmq_aws:request/6`` | Perform a request specifying the service, method, path, headers, body, and ``httpc:http_options().``
71-
``rabbitmq_aws:request/7`` | Perform a request specifying the service, method, path, headers, body, ``httpc:http_options()``, and override the API endpoint.
72-
58+
59+
Method | Description
60+
-------------------------------------------|--------------------------------------------------------------------------------------------
61+
`rabbitmq_aws:set_region/1` | Manually specify the AWS region to make requests to.
62+
`rabbitmq_aws:set_credentials/2` | Manually specify the request credentials to use.
63+
`rabbitmq_aws:refresh_credentials/0` | Refresh the credentials from the environment, filesystem, or EC2 Instance Metadata Service.
64+
`rabbitmq_aws:ensure_imdsv2_token_valid/0` | Make sure EC2 IMDSv2 token is active and valid.
65+
`rabbitmq_aws:get/2` | Perform a GET request to the API specifying the service and request path.
66+
`rabbitmq_aws:get/3` | Perform a GET request specifying the service, path, and headers.
67+
`rabbitmq_aws:post/4` | Perform a POST request specifying the service, path, headers, and body.
68+
`rabbitmq_aws:request/5` | Perform a request specifying the service, method, path, headers, and body.
69+
`rabbitmq_aws:request/6` | Perform a request specifying the service, method, path, headers, body, and `httpc:http_options().`
70+
`rabbitmq_aws:request/7` | Perform a request specifying the service, method, path, headers, body, `httpc:http_options()`, and override the API endpoint.
71+
`rabbitmq_aws:api_get_request/2` | Perform an AWS service API request with retries.
72+
`rabbitmq_aws:api_post_request/2` | Perform an AWS service API request with retries.
7373

7474
## Example Usage
7575

@@ -80,8 +80,7 @@ you're using the EC2 Instance Metadata Service for credentials:
8080
application:start(rabbitmq_aws).
8181
{ok, {Headers, Response}} = rabbitmq_aws:get("ec2","/?Action=DescribeTags&Version=2015-10-01").
8282
```
83-
84-
To configure credentials, invoke ``rabbitmq_aws:set_credentials/2``:
83+
To configure credentials, invoke `rabbitmq_aws:set_credentials/2`:
8584

8685
```erlang
8786
application:start(rabbitmq_aws).
@@ -90,8 +89,8 @@ rabbitmq_aws:set_credentials("AKIDEXAMPLE", "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMP
9089

9190
RequestHeaders = [{"Content-Type", "application/x-amz-json-1.0"},
9291
{"X-Amz-Target", "DynamoDB_20120810.ListTables"}],
93-
94-
{ok, {Headers, Response}} = rabbitmq_aws:post("dynamodb", "/",
92+
93+
{ok, {Headers, Response}} = rabbitmq_aws:post("dynamodb", "/",
9594
"{\"Limit\": 20}",
9695
RequestHeaders).
9796
```

deps/rabbitmq_aws/src/rabbitmq_aws.erl

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
has_credentials/0,
2020
set_region/1,
2121
ensure_imdsv2_token_valid/0,
22-
api_get_request/2
22+
api_get_request/2,
23+
api_post_request/4
2324
]).
2425

2526
%% gen-server exports
@@ -622,8 +623,10 @@ ensure_credentials_valid() ->
622623
case has_credentials(State) of
623624
true ->
624625
case expired_credentials(State#state.expiration) of
625-
true -> refresh_credentials(State);
626-
_ -> ok
626+
true ->
627+
refresh_credentials(State);
628+
_ ->
629+
ok
627630
end;
628631
_ ->
629632
refresh_credentials(State)
@@ -633,19 +636,46 @@ ensure_credentials_valid() ->
633636
%% @doc Invoke an API call to an AWS service.
634637
%% @end
635638
api_get_request(Service, Path) ->
636-
?LOG_DEBUG("Invoking AWS request {Service: ~tp; Path: ~tp}...", [Service, Path]),
637-
api_get_request_with_retries(Service, Path, ?MAX_RETRIES, ?LINEAR_BACK_OFF_MILLIS).
639+
?LOG_DEBUG("invoking AWS get request {Service: ~tp; Path: ~tp}...", [Service, Path]),
640+
api_request_with_retries(Service, get, Path, "", [],
641+
?MAX_RETRIES, ?LINEAR_BACK_OFF_MILLIS).
638642

639-
-spec api_get_request_with_retries(string(), path(), integer(), integer()) ->
643+
-spec api_post_request(
644+
Service :: string(),
645+
Path :: path(),
646+
Body :: body(),
647+
Headers :: headers()
648+
) -> result().
649+
%% @doc Perform a HTTP Post request to the AWS API for the specified service. The
650+
%% response will automatically be decoded if it is either in JSON or XML
651+
%% format.
652+
%% @end
653+
api_post_request(Service, Path, Body, Headers) ->
654+
?LOG_DEBUG("invoking AWS post request {Service: ~tp; Path: ~tp}...", [Service, Path]),
655+
api_request_with_retries(Service, post, Path, Body, Headers,
656+
?MAX_RETRIES, ?LINEAR_BACK_OFF_MILLIS).
657+
658+
-spec api_request_with_retries(
659+
Service :: string(),
660+
Method :: method(),
661+
Path :: path(),
662+
Body :: body(),
663+
Headers :: headers(),
664+
Retries :: integer(),
665+
WaitTime :: integer()) ->
640666
{'ok', list()} | {'error', term()}.
641667
%% @doc Invoke an API call to an AWS service with retries.
642668
%% @end
643-
api_get_request_with_retries(_, _, 0, _) ->
644-
?LOG_WARNING("Request to AWS service has failed after ~b retries", [?MAX_RETRIES]),
669+
api_request_with_retries(_, _, _, _, _, 0, _) ->
670+
?LOG_ERROR("Request to AWS service has failed after ~b retries", [?MAX_RETRIES]),
645671
{error, "AWS service is unavailable"};
646-
api_get_request_with_retries(Service, Path, Retries, WaitTimeBetweenRetries) ->
647-
ensure_credentials_valid(),
648-
case get(Service, Path) of
672+
api_request_with_retries(Service, Method, Path, Body, Headers, Retries, WaitTime) ->
673+
case ensure_credentials_valid() of
674+
ok -> ok;
675+
Error ->
676+
?LOG_WARNING("error during credentials check: ~tp", [Error])
677+
end,
678+
case request(Service, Method, Path, Body, Headers) of
649679
{ok, {_Headers, Payload}} ->
650680
?LOG_DEBUG("AWS request: ~ts~nResponse: ~tp", [Path, Payload]),
651681
{ok, Payload};
@@ -660,6 +690,6 @@ api_get_request_with_retries(Service, Path, Retries, WaitTimeBetweenRetries) ->
660690
ok
661691
end,
662692
?LOG_WARNING("Will retry AWS request, remaining retries: ~b", [Retries]),
663-
timer:sleep(WaitTimeBetweenRetries),
664-
api_get_request_with_retries(Service, Path, Retries - 1, WaitTimeBetweenRetries)
693+
timer:sleep(WaitTime),
694+
api_request_with_retries(Service, Method, Path, Body, Headers, Retries - 1, WaitTime)
665695
end.

deps/rabbitmq_aws/test/rabbitmq_aws_tests.erl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ api_get_request_test_() ->
605605
{ok, Pid} = rabbitmq_aws:start_link(),
606606
rabbitmq_aws:set_region("us-east-1"),
607607
rabbitmq_aws:set_credentials(State),
608-
Result = rabbitmq_aws:api_get_request_with_retries("AWS", "API", 3, 1),
608+
Result = rabbitmq_aws:api_request_with_retries("AWS", get, "API", "", [], 3, 1),
609609
ok = gen_server:stop(Pid),
610610
?assertEqual({error, "AWS service is unavailable"}, Result),
611611
meck:validate(httpc)
@@ -638,7 +638,7 @@ api_get_request_test_() ->
638638
{ok, Pid} = rabbitmq_aws:start_link(),
639639
rabbitmq_aws:set_region("us-east-1"),
640640
rabbitmq_aws:set_credentials(State),
641-
Result = rabbitmq_aws:api_get_request_with_retries("AWS", "API", 3, 1),
641+
Result = rabbitmq_aws:api_request_with_retries("AWS", get, "API", "", [], 3, 1),
642642
ok = gen_server:stop(Pid),
643643
?assertEqual({ok, [{"data", "value"}]}, Result),
644644
meck:validate(httpc)

0 commit comments

Comments
 (0)