From 416539a6acb4391b52f80d91b96fdab07658953d Mon Sep 17 00:00:00 2001 From: Tiago Freire Date: Mon, 22 Aug 2016 21:26:56 -0300 Subject: WIP - Add elixir GenServer --- lib/http_client.ex | 18 -------- lib/powerdnsex.ex | 68 ++++++++++++++++++++++++++++ lib/powerdnsex/config.ex | 7 ++- lib/powerdnsex/http_client.ex | 16 +++++++ lib/powerdnsex/managers/records_manager.ex | 17 +++++-- lib/powerdnsex/managers/zones_manager.ex | 2 +- lib/powerdnsex/models/record.ex | 8 ++++ lib/powerdnsex/models/resource_record_set.ex | 20 ++++++++ lib/powerdnsex/server_setup.ex | 29 ++++++++++++ 9 files changed, 159 insertions(+), 26 deletions(-) delete mode 100644 lib/http_client.ex create mode 100644 lib/powerdnsex/http_client.ex create mode 100644 lib/powerdnsex/server_setup.ex (limited to 'lib') diff --git a/lib/http_client.ex b/lib/http_client.ex deleted file mode 100644 index 6d18cbe..0000000 --- a/lib/http_client.ex +++ /dev/null @@ -1,18 +0,0 @@ -defmodule PowerDNSex.HttpClient do - @moduledoc""" - Client to do http requests for PowerDns API - """ - - use HTTPoison.Base - - alias PowerDNSex.Config - - def process_url(url) do - Config.powerdns_url <> url - end - - defp process_request_headers(headers) do - custom = ["X-API-Key": Config.powerdns_token] - Enum.into(headers, custom) - end -end diff --git a/lib/powerdnsex.ex b/lib/powerdnsex.ex index c82aa59..7152417 100644 --- a/lib/powerdnsex.ex +++ b/lib/powerdnsex.ex @@ -1,2 +1,70 @@ defmodule PowerDNSex do + @default_server "localhost" + use PowerDNSex.ServerSetup + + alias PowerDNSex.Managers.{ZonesManager, RecordsManager} + alias PowerDNSex.Models.Zone + + ### + # Zones + ### + + @spec create_zone(Zone.t, String.t) :: :ok | {:error, String.t} + @doc """ + Create a new Zone on PowerDNS + """ + def create_zone(%Zone{} = zone, server_name \\ @default_server) do + ZonesManager.create(zone, server_name) + end + + @spec show_zone(Zone.t, String.t) :: :ok | {:error, String.t} + @doc """ + Show / Retrive info of the specific Zone + """ + def show_zone(%Zone{} = zone, server_name \\ @default_server) do + ZonesManager.show(zone, server_name) + end + + @spec delete_zone(Zone.t, String.t) :: :ok | {:error, String.t} + @doc """ + Delete specific Zone on PowerDNS + """ + def delete_zone(%Zone{} = zone, server_name \\ @default_server) do + ZonesManager.delete(zone, server_name) + end + + ### + # Records + ### + @spec create_record(Zone.t, struct) :: :ok | {:error, String.t} + @doc """ + Create a new Record for the given Zone + """ + def create_record(%Zone{} = zone, %{} = rrset_attrs) do + RecordsManager.create(zone, rrset_attrs) + end + + @spec show_record(Zone.t, struct) :: :ok | {:error, String.t} + @doc """ + Show / Retrive info of the specific Record of the given Zone + """ + def show_record(%Zone{} = zone, %{} = rrset_attrs) do + RecordsManager.show(zone, rrset_attrs) + end + + @spec update_record(Zone.t, struct) :: :ok | {:error, String.t} + @doc """ + Update Record of the given Zone + """ + def update_record(%Zone{} = zone, %{} = rrset_attrs) do + RecordsManager.update(zone, rrset_attrs) + end + + @spec delete_record(Zone.t, struct) :: :ok | {:error, String.t} + @doc """ + Delete specific Record of given Zone + """ + def delete_record(%Zone{} = zone, %{} = rrset_attrs) do + RecordsManager.delete(zone, rrset_attrs) + end end diff --git a/lib/powerdnsex/config.ex b/lib/powerdnsex/config.ex index 50589d4..486ccb6 100644 --- a/lib/powerdnsex/config.ex +++ b/lib/powerdnsex/config.ex @@ -14,12 +14,11 @@ defmodule PowerDNSex.Config do end def powerdns_url do - data.url + url = data.url + if String.ends_with?(url, "/"), do: url, else: url <> "/" end - def powerdns_token do - data.token - end + def powerdns_token, do: data.token ### # Private diff --git a/lib/powerdnsex/http_client.ex b/lib/powerdnsex/http_client.ex new file mode 100644 index 0000000..0a242b5 --- /dev/null +++ b/lib/powerdnsex/http_client.ex @@ -0,0 +1,16 @@ +defmodule PowerDNSex.HttpClient do + @moduledoc""" + Client to do http requests for PowerDns API + """ + + use HTTPoison.Base + + alias PowerDNSex.Config + + def process_url(url), do: Config.powerdns_url <> url + + defp process_request_headers(headers) do + custom = ["X-API-Key": Config.powerdns_token] + Enum.into(headers, custom) + end +end diff --git a/lib/powerdnsex/managers/records_manager.ex b/lib/powerdnsex/managers/records_manager.ex index 7ac83ca..a8c67e5 100644 --- a/lib/powerdnsex/managers/records_manager.ex +++ b/lib/powerdnsex/managers/records_manager.ex @@ -1,8 +1,9 @@ -defmodule PowerDNSex.RecordsManager do +defmodule PowerDNSex.Managers.RecordsManager do alias PowerDNSex.HttpClient alias PowerDNSex.Models.{Zone, Record, Error} - alias PowerDNSex.Models.ResourceRecordSet, as: RRset + alias PowerDNSex.Models.ResourceRecordSet, as: RRSet + alias PowerDNSex.Managers.ZonesManager alias HTTPoison.Response @@ -11,6 +12,11 @@ defmodule PowerDNSex.RecordsManager do patch(zone, rrset_attrs) end + def show(zone_name, %{} = rrset_attrs) do + zone = ZonesManager.show(zone_name) + RRSet.find(zone.rrsets, rrset_attrs) + end + def update(%Zone{} = zone, %{} = rrset_attrs) do rrset_attrs = Map.merge(rrset_attrs, %{changetype: "REPLACE"}) patch(zone, rrset_attrs) @@ -38,7 +44,12 @@ defmodule PowerDNSex.RecordsManager do defp patch(%Zone{} = zone, %{} = rrset_attrs) do zone.url - |> HttpClient.patch!(RRset.as_body(RRset.build(rrset_attrs))) + |> HttpClient.patch!(RRSet.as_body(RRSet.build(rrset_attrs))) |> process_request_response end + + defp has_attrs?(rrset, attrs) do + Map.keys(attrs) + |> Enum.all?(&(equal_attr?(&1, attrs[&1], rrsets))) + end end diff --git a/lib/powerdnsex/managers/zones_manager.ex b/lib/powerdnsex/managers/zones_manager.ex index ebad7fe..260adbb 100644 --- a/lib/powerdnsex/managers/zones_manager.ex +++ b/lib/powerdnsex/managers/zones_manager.ex @@ -1,4 +1,4 @@ -defmodule PowerDNSex.ZonesManager do +defmodule PowerDNSex.Managers.ZonesManager do @default_server "localhost" diff --git a/lib/powerdnsex/models/record.ex b/lib/powerdnsex/models/record.ex index a494a07..9ffc2b7 100644 --- a/lib/powerdnsex/models/record.ex +++ b/lib/powerdnsex/models/record.ex @@ -26,4 +26,12 @@ defmodule PowerDNSex.Models.Record do def as_body(record_attrs) when is_tuple(record_attrs) do %{content: elem(record_attrs, 0), disabled: elem(record_attrs, 1)} end + + def find(records, attrs) when is_list(records) do + Enum.find(records, fn(record)-> + Enum.all?(attrs, fn({attr, attr_value})-> + Map.get(record, attr) == attr_value + end) + end) + end end diff --git a/lib/powerdnsex/models/resource_record_set.ex b/lib/powerdnsex/models/resource_record_set.ex index f4338a2..9f248ab 100644 --- a/lib/powerdnsex/models/resource_record_set.ex +++ b/lib/powerdnsex/models/resource_record_set.ex @@ -25,6 +25,22 @@ defmodule PowerDNSex.Models.ResourceRecordSet do |> Poison.encode! end + def find(rrsets, %{} = attrs) when is_list(rrsets) do + Enum.find(rrsets, fn(rrset)-> + Enum.all?(attrs, fn({attr, attr_value})-> + if Enum.member?(Map.keys(%__MODULE__{}), attr) do + equal_attr?(attr, attr_value, rrset) + else + Record.find(rrset.records, %{attr => attr_value}) + end + end) + end) + end + + ### + # Private + ### + defp set_attrs(rrset, attr_name, attrs) do if Map.has_key?(attrs, attr_name) do attr_value = case attr_name do @@ -37,4 +53,8 @@ defmodule PowerDNSex.Models.ResourceRecordSet do rrset end end + + defp equal_attr?(attr, attr_value, rrset) do + Map.get(rrset, attr) == attr_value + end end diff --git a/lib/powerdnsex/server_setup.ex b/lib/powerdnsex/server_setup.ex new file mode 100644 index 0000000..3b5cb14 --- /dev/null +++ b/lib/powerdnsex/server_setup.ex @@ -0,0 +1,29 @@ +defmodule PowerDNSex.ServerSetup do + defmacro __using__(opts \\ []) do + quote bind_quoted: [opts: opts] do + use Application + + @name opts[:process_name] || :PowerDNSex + @config opts[:config] + + @spec start(term, term) :: GenServer.on_start + def start(_, _), do: start + + @spec start() :: GenServer.on_start + @doc false + def start do + import Supervisor.Spec + + children = [worker(Server, [@name, @config])] + + options = [strategy: :one_for_one, name: :"#{@name}.Supervisor"] + + case Supervisor.start_link(children, options) do + {:ok, pid} -> {:ok, pid} + {:error, {:already_started, pid}} -> {:ok, pid} + other -> other + end + end + end + end +end -- cgit v1.2.3