diff --git a/README.md b/README.md
index e58d028..3cf0fda 100644
--- a/README.md
+++ b/README.md
@@ -91,6 +91,8 @@ Parsers are currently implemented for the following actions:
* GetUser
* ListAccessKeys
* ListGroup
+ * ListRoles
+ * ListRoleTags
* ListUsers
* UpdateAccessKey
* UpdateGroup
diff --git a/lib/ex_aws/iam.ex b/lib/ex_aws/iam.ex
index b683d4a..a159eab 100644
--- a/lib/ex_aws/iam.ex
+++ b/lib/ex_aws/iam.ex
@@ -47,6 +47,8 @@ defmodule ExAws.Iam do
* GetUser
* ListAccessKeys
* ListGroup
+ * ListRoles
+ * ListRoleTags
* ListUsers
* UpdateAccessKey
* UpdateGroup
@@ -76,8 +78,9 @@ defmodule ExAws.Iam do
@shared_opts [version: "2010-05-08"]
@doc """
- Generates an ExAws operation for the given IAM API action. See the AWS IAM
- API Reference for a list of available actions and their parameters.
+ Generates an ExAws operation for the given IAM API action.
+
+ See the AWS IAM API Reference for a list of available actions.
* https://docs.aws.amazon.com/IAM/latest/APIReference
@@ -85,10 +88,12 @@ defmodule ExAws.Iam do
* `action` - The name of the action you want to call. Should be a _CamelCase_ string.
- * `params` - A keyword list of any params the action accepts.
+ * `params` - A keyword list of any params the action takes.
## Options
+ Any options that the given action
+
* `parser` - A function to parse the request result. Defaults
to `Parser.parser/2`.
@@ -405,6 +410,48 @@ defmodule ExAws.Iam do
operation(:delete_group, [group_name: name] ++ opts)
end
+ @doc """
+ Creates an ExAws operation for a `ListRoles` IAM request.
+
+ ## Options
+
+ * `:marker` - Use this parameter only when paginating results.
+
+ * `:max_items` - Use this only when paginating results to indicate
+ the maximum number of items you want in the response.
+
+ * `:path_prefix` - The path prefix for filtering the results.
+
+ See shared options in moduledoc.
+
+ """
+ def list_roles(opts \\ []) do
+ operation(:list_roles, opts)
+ end
+
+ @doc """
+ Creates an ExAws operation for a `ListRoleTags` IAM request.
+
+ ## Parameters
+
+ * `role_name` - The name of the role to return for which you want to get the list of tags.
+
+ ## Options
+
+ * `:marker` - Use this parameter only when paginating results.
+
+ * `:max_items` - Use this only when paginating results to indicate
+ the maximum number of items you want in the response.
+
+ * `:path_prefix` - The path prefix for filtering the results.
+
+ See shared options in moduledoc.
+
+ """
+ def list_role_tags(role_name, opts \\ []) do
+ operation(:list_role_tags, [role_name: role_name] ++ opts)
+ end
+
defp to_operation(params, opts) do
%ExAws.Operation.Query{
action: params["Action"],
diff --git a/lib/ex_aws/iam/parser.ex b/lib/ex_aws/iam/parser.ex
index 17c1a9d..2e7ef1b 100644
--- a/lib/ex_aws/iam/parser.ex
+++ b/lib/ex_aws/iam/parser.ex
@@ -14,6 +14,7 @@ defmodule ExAws.Iam.Parser do
AccessKey,
Group,
Metadata,
+ Role,
User
}
@@ -58,6 +59,15 @@ defmodule ExAws.Iam.Parser do
Group.parse(xml, action)
end
+ @role_actions ~w[
+ ListRoles
+ ListRoleTags
+ ]
+
+ defp dispatch(xml, action) when action in @role_actions do
+ Role.parse(xml, action)
+ end
+
@metadata_only_actions ~w[
UpdateAccessKey
UpdateGroup
diff --git a/lib/ex_aws/iam/parsers/role.ex b/lib/ex_aws/iam/parsers/role.ex
new file mode 100644
index 0000000..671e62c
--- /dev/null
+++ b/lib/ex_aws/iam/parsers/role.ex
@@ -0,0 +1,55 @@
+defmodule ExAws.Iam.Parsers.Role do
+ @moduledoc """
+ Defines parsers for handling AWS IAM `Role` query reponses.
+
+ """
+
+ import SweetXml, only: [sigil_x: 2]
+ import ExAws.Iam.Utils, only: [response_metadata_path: 0]
+
+ @doc """
+ Parses XML from IAM `ListRoles` response.
+
+ """
+ def parse(xml, "ListRoles") do
+ SweetXml.xpath(xml, ~x"//ListRolesResponse",
+ list_roles_result: [
+ ~x"//ListRolesResult",
+ is_truncated: ~x"./IsTruncated/text()"s,
+ marker: ~x"./Marker/text()"o,
+ roles: [
+ ~x"./Roles/member"l,
+ path: ~x"./Path/text()"s,
+ role_name: ~x"./RoleName/text()"s,
+ arn: ~x"./Arn/text()"s,
+ role_id: ~x"./RoleId/text()"s,
+ create_date: ~x"./CreateDate/text()"s,
+ max_session_duration: ~x"./MaxSessionDuration/text()"s,
+ assume_role_policy_document:
+ ~x"./AssumeRolePolicyDocument/text()"s |> SweetXml.transform_by(&URI.decode/1)
+ ]
+ ],
+ response_metadata: response_metadata_path()
+ )
+ end
+
+ @doc """
+ Parses XML from IAM `ListRoleTags` response.
+
+ """
+ def parse(xml, "ListRoleTags") do
+ SweetXml.xpath(xml, ~x"//ListRoleTagsResponse",
+ list_role_tags_result: [
+ ~x"//ListRoleTagsResult",
+ is_truncated: ~x"./IsTruncated/text()"s,
+ marker: ~x"./Marker/text()"o,
+ tags: [
+ ~x"./Tags/member"l,
+ key: ~x"./Key/text()"s,
+ value: ~x"./Value/text()"s
+ ]
+ ],
+ response_metadata: response_metadata_path()
+ )
+ end
+end
diff --git a/test/lib/iam/parsers/role_test.exs b/test/lib/iam/parsers/role_test.exs
new file mode 100644
index 0000000..9b9ddd3
--- /dev/null
+++ b/test/lib/iam/parsers/role_test.exs
@@ -0,0 +1,62 @@
+defmodule ExAws.Iam.Parsers.RoleTest do
+ use ExUnit.Case
+
+ import ExAws.Iam.TestHelper, only: [read_file: 2]
+
+ alias ExAws.Iam.Parser
+
+ test "list_roles/2" do
+ xml = read_file("role", "list_roles")
+ response = {:ok, %{body: xml, status_code: 200}}
+
+ expected =
+ {:ok,
+ %{
+ body: %{
+ list_roles_result: %{
+ is_truncated: "false",
+ marker: nil,
+ roles: [
+ %{
+ arn: "arn:aws:iam::085326204011:role/foo",
+ assume_role_policy_document:
+ "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ec2.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}",
+ create_date: "2018-10-19T22:04:37Z",
+ max_session_duration: "3600",
+ path: "/",
+ role_id: "AGPAIDI3XY2DD433B73WG",
+ role_name: "foo"
+ }
+ ]
+ },
+ response_metadata: %{request_id: "81ca4919-d3fb-11e8-986e-5fbe089ad211"}
+ },
+ status_code: 200
+ }}
+
+ assert expected == Parser.parse(response, "ListRoles")
+ end
+
+ test "list_role_tags/2" do
+ xml = read_file("role", "list_role_tags")
+ response = {:ok, %{body: xml, status_code: 200}}
+
+ expected =
+ {:ok,
+ %{
+ body: %{
+ list_role_tags_result: %{
+ is_truncated: "false",
+ marker: nil,
+ tags: [
+ %{key: "UserRole", value: "developer"}
+ ]
+ },
+ response_metadata: %{request_id: "81ca4919-d3fb-11e8-986e-5fbe089ad211"}
+ },
+ status_code: 200
+ }}
+
+ assert expected == Parser.parse(response, "ListRoleTags")
+ end
+end
diff --git a/test/lib/iam_test.exs b/test/lib/iam_test.exs
index 0975cbe..6529461 100644
--- a/test/lib/iam_test.exs
+++ b/test/lib/iam_test.exs
@@ -425,4 +425,46 @@ defmodule ExAws.IamTest do
assert Iam.delete_group("my_group") == expected
end
end
+
+ describe "Role" do
+ test "list_roles/0 returns an ExAws ListRoles op struct" do
+ opts = [
+ marker: "abc",
+ max_items: 50,
+ path_prefix: "/prefix"
+ ]
+
+ expected = %ExAws.Operation.Query{
+ action: "ListRoles",
+ params: %{
+ "Action" => "ListRoles",
+ "Marker" => "abc",
+ "MaxItems" => 50,
+ "PathPrefix" => "/prefix",
+ "Version" => "2010-05-08"
+ },
+ parser: &Parser.parse/2,
+ path: "/",
+ service: :iam
+ }
+
+ assert Iam.list_roles(opts) == expected
+ end
+
+ test "list_role_tags/1 returns an ExAws ListRoleTags op struct" do
+ expected = %ExAws.Operation.Query{
+ action: "ListRoleTags",
+ params: %{
+ "Action" => "ListRoleTags",
+ "RoleName" => "foo",
+ "Version" => "2010-05-08"
+ },
+ parser: &Parser.parse/2,
+ path: "/",
+ service: :iam
+ }
+
+ assert Iam.list_role_tags("foo") == expected
+ end
+ end
end
diff --git a/test/support/responses/role/list_role_tags.xml b/test/support/responses/role/list_role_tags.xml
new file mode 100644
index 0000000..9a0678d
--- /dev/null
+++ b/test/support/responses/role/list_role_tags.xml
@@ -0,0 +1,14 @@
+
+
+ false
+
+
+ developer
+ UserRole
+
+
+
+
+ 81ca4919-d3fb-11e8-986e-5fbe089ad211
+
+
diff --git a/test/support/responses/role/list_roles.xml b/test/support/responses/role/list_roles.xml
new file mode 100644
index 0000000..9032fdf
--- /dev/null
+++ b/test/support/responses/role/list_roles.xml
@@ -0,0 +1,19 @@
+
+
+ false
+
+
+ /
+ %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Principal%22%3A%7B%22Service%22%3A%22ec2.amazonaws.com%22%7D%2C%22Action%22%3A%22sts%3AAssumeRole%22%7D%5D%7D
+ 3600
+ AGPAIDI3XY2DD433B73WG
+ foo
+ arn:aws:iam::085326204011:role/foo
+ 2018-10-19T22:04:37Z
+
+
+
+
+ 81ca4919-d3fb-11e8-986e-5fbe089ad211
+
+