defmodule ExAws.Route53 do
import ExAws.Utils, only: [uuid: 0, upcase: 1, rename_keys: 2]
import ExAws.Route53.Xml, only: [add_optional_node: 2]
alias ExAws.Route53.Xml
@moduledoc """
Operations on AWS Route53
"""
@type record_type :: [
:a | :aaaa | :cname | :mx | :naptr | :ns | :ptr | :soa | :spf | :srv | :txt
]
@xmlns "https://route53.amazonaws.com/doc/2013-04-01/"
@type list_hosted_zones_opts :: [
{:marker, binary}
| {:max_items, 1..100}
]
@doc "List hosted zones"
@spec list_hosted_zones(opts :: list_hosted_zones_opts) :: ExAws.Operation.RestQuery.t()
def list_hosted_zones(opts \\ []) do
request(:get, :list_hosted_zones, params: opts)
end
@type create_hosted_zone_opts :: [
{:name, binary}
| {:comment, binary}
| {:delegation_set, binary}
| {:private, boolean}
| {:vpc_is, binary}
| {:vpc_region, binary}
]
@doc "Create hosted zone"
@spec create_hosted_zone(opts :: create_hosted_zone_opts) :: ExAws.Operation.RestQuery.t()
def create_hosted_zone(opts \\ []) do
payload =
{
:CreateHostedZoneRequest,
%{xmlns: @xmlns},
[
{:CallerReference, nil, uuid()},
{:Name, nil, opts[:name]}
]
}
|> add_optional_node({:DelegationSetId, nil, opts[:delegation_set]})
|> add_optional_node(
{:HostedZoneConfig, nil, nil}
|> add_optional_node({:Comment, nil, opts[:comment]})
|> add_optional_node({:PrivateZone, nil, opts[:private]})
)
|> add_optional_node({
:VPC,
nil,
[
{:VPCId, nil, opts[:vpc_id]},
{:VPCRegion, nil, opts[:vpc_region]}
]
})
|> Xml.build()
request(:post, :create_hosted_zone, body: payload)
end
@doc "Delete hosted zone"
@spec delete_hosted_zone(id :: String.t()) :: ExAws.Operation.RestQuery.t()
def delete_hosted_zone(id) do
request(:delete, :delete_hosted_zone, path: "/#{id}")
end
@type record_action :: [:create | :delete | :upsert]
@type record_opts :: [
{:action, record_action}
| {:name, binary}
| {:type, record_type}
| {:ttl, integer()}
| {:records, [String.t(), ...]}
]
@type change_record_sets_opts :: [
{:comment, binary}
| {:action, record_action}
| {:name, binary}
| {:type, record_type}
| {:ttl, non_neg_integer}
| {:records, [String.t(), ...]}
| {:batch, [record_opts, ...]}
]
@doc "Change resource record sets"
@spec change_record_sets(id :: String.t(), opts :: change_record_sets_opts) ::
ExAws.Operation.RestQuery.t()
def change_record_sets(id, opts \\ []) do
changes = opts |> Keyword.get(:batch, Map.new(opts)) |> List.wrap()
payload =
{
:ChangeResourceRecordSetsRequest,
%{xmlns: @xmlns},
[
{:ChangeBatch, nil,
[
{:Changes, nil,
[
changes
|> Enum.map(fn change ->
{:Change, nil,
[
{:Action, nil, upcase(change[:action])},
{:ResourceRecordSet, nil,
[
{:Name, nil, change[:name]},
{:Type, nil, upcase(change[:type])},
{:TTL, nil, change[:ttl]},
{:ResourceRecords, nil,
change
|> Map.get(:records, [])
|> Enum.map(fn value ->
{:ResourceRecord, nil,
[
{:Value, nil, value}
]}
end)}
]}
]}
end)
]},
{:Comment, nil, opts[:comment]}
]}
]
}
|> Xml.build()
request(:post, :change_record_sets, path: "/#{id}/rrset", body: payload)
end
@doc "List resource record sets"
@type list_record_sets_opts :: [
{:identifier, binary}
| {:name, binary}
| {:type, record_type}
| {:max_items, non_neg_integer}
]
@spec list_record_sets(id :: String.t(), opts :: list_record_sets_opts) ::
ExAws.Operation.RestQuery.t()
def list_record_sets(id, opts \\ []) do
request(:get, :list_record_sets, path: "/#{id}/rrset", params: opts)
end
## Request
######################
defp request(http_method, action, opts) do
path = Keyword.get(opts, :path, "")
params = opts |> Keyword.get(:params, []) |> rename_keys(max_items: :maxitems) |> Map.new()
%ExAws.Operation.RestQuery{
http_method: http_method,
path: "/2013-04-01/hostedzone#{path}",
params: params,
body: Keyword.get(opts, :body, ""),
service: :route53,
action: action,
parser: &ExAws.Route53.Parsers.parse/2
}
end
end