From ab206a90b61f7b411dae49e0676cd64165ee10f2 Mon Sep 17 00:00:00 2001 From: Lindolfo 'Lorn' Rodrigues Date: Wed, 13 Feb 2019 16:40:19 -0200 Subject: Support Elixir-1.8 Also dropped support for elixir < 1.6 --- .formatter.exs | 4 ++ .travis.yml | 27 +++++---- Dockerfile | 12 ++++ README.md | 32 ++++++++++ config/config.exs | 3 +- docker-compose.yml | 9 +++ lib/powerdnsex.ex | 23 ++++---- lib/powerdnsex/config.ex | 22 ++++--- lib/powerdnsex/converter.ex | 9 ++- lib/powerdnsex/gen_server/server.ex | 6 +- lib/powerdnsex/http_client.ex | 10 ++-- lib/powerdnsex/managers/records_manager.ex | 8 ++- lib/powerdnsex/managers/zones_manager.ex | 24 ++++---- lib/powerdnsex/models/error.ex | 2 +- lib/powerdnsex/models/record.ex | 4 +- lib/powerdnsex/models/resource_record_set.ex | 69 ++++++++++++---------- lib/powerdnsex/models/zone.ex | 23 ++++++-- mix.exs | 29 ++++----- mix.lock | 21 ++++--- script/clean | 3 + script/common.sh | 8 +++ script/coverage | 5 ++ script/credo | 7 +++ script/docs | 5 ++ script/reset | 3 + script/run | 9 +++ script/setup | 6 ++ script/test | 7 +++ test/lib/powerdnsex/config_test.exs | 20 +++---- .../powerdnsex/managers/records_manager_test.exs | 23 ++++---- .../lib/powerdnsex/managers/zones_manager_test.exs | 52 +++++++++------- .../powerdnsex/models/resource_record_set_test.exs | 64 +++++++++++--------- test/lib/powerdnsex/models/zone_test.exs | 1 + test/lib/powerdnsex/powerdnsex_test.exs | 14 +++-- test/support/fake_config.exs | 1 - test/test_helper.exs | 6 +- 36 files changed, 366 insertions(+), 205 deletions(-) create mode 100644 .formatter.exs create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100755 script/clean create mode 100644 script/common.sh create mode 100755 script/coverage create mode 100755 script/credo create mode 100755 script/docs create mode 100755 script/reset create mode 100755 script/run create mode 100755 script/setup create mode 100755 script/test diff --git a/.formatter.exs b/.formatter.exs new file mode 100644 index 0000000..650bb88 --- /dev/null +++ b/.formatter.exs @@ -0,0 +1,4 @@ +[ + inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"] +] + diff --git a/.travis.yml b/.travis.yml index 8109625..56473e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,22 +2,23 @@ language: elixir elixir: - - 1.3 - - 1.4 - - 1.5 + - 1.6 + - 1.7 + - 1.8 otp_release: - - 17.4 - - 18.3 - 19.3 - 20.0 + - 21.0 + +script: mix test matrix: - exclude: - - elixir: 1.3 - otp_release: 20.0 -# - elixir: 1.4 -# otp_release: 17.4 -# - elixir: 1.4 -# otp_release: 18.3 + include: + - elixir: '1.6.6' + otp_release: '19.3.6' + + - elixir: '1.7.4' + otp_release: '20.0' -script: mix test \ No newline at end of file + - elixir: '1.7.4' +otp_release: '21.0' diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6413529 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM elixir:1.8 + +RUN mkdir -p /opt/power_dnsex/ +ENV LC_ALL C.UTF-8 +WORKDIR /opt/power_dnsex + +ADD mix.exs /opt/power_dnsex/mix.exs +ADD mix.lock /opt/power_dnsex/mix.lock +RUN mix do local.hex --force, local.rebar --force + +EXPOSE 4000 +CMD ["/bin/bash"] diff --git a/README.md b/README.md index 2f161b0..3aba62c 100644 --- a/README.md +++ b/README.md @@ -111,3 +111,35 @@ rrset = PowerDNSex.show_record("example.com", record) res = PowerDNSex.delete_record(zone, rrset) ``` +## Development + +### Setup application +```bash +$ script/setup +``` + +### Run local console (IEX) +```bash +$ script/run +``` + +### Run tests +```bash +$ script/test +``` + +#### Run tests to a specific File +```bash +$ script/test test/lib/powerdnsex/powerdnsex_test.exs +``` + +### Reset environment (clean + setup) +### YOU WILL LOSE EVERYTHING + +Good for then you change the elixir version and need to delete everything and start again + +```bash +$ script/reset +``` + + diff --git a/config/config.exs b/config/config.exs index 8eff0b9..8233fe9 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1,4 +1,3 @@ use Mix.Config -import_config "#{Mix.env}.exs" - +import_config "#{Mix.env()}.exs" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..6fe6fa2 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,9 @@ +version: '3' +services: + web: + tty: true + stdin_open: true + build: . + command: 'iex -S mix' + volumes: + - .:/opt/power_dnsex diff --git a/lib/powerdnsex.ex b/lib/powerdnsex.ex index 0f7876b..6568319 100644 --- a/lib/powerdnsex.ex +++ b/lib/powerdnsex.ex @@ -5,9 +5,9 @@ defmodule PowerDNSex do @name :PowerDNSex - def start(_,_), do: start() + def start(_, _), do: start() - @spec start() :: GenServer.on_start + @spec start() :: GenServer.on_start() @doc false def start() do import Supervisor.Spec @@ -16,7 +16,7 @@ defmodule PowerDNSex do options = [strategy: :one_for_one, name: :"#{@name}.Supervisor"] try do - Config.valid? + Config.valid?() case Supervisor.start_link(children, options) do {:ok, pid} -> {:ok, pid} @@ -34,7 +34,7 @@ defmodule PowerDNSex do # Zones # ######### - @spec create_zone(Zone.t, String.t) :: Zone.t | Error.t + @spec create_zone(Zone.t(), String.t()) :: Zone.t() | Error.t() @doc """ Create a new Zone on PowerDNS """ @@ -42,8 +42,7 @@ defmodule PowerDNSex do call({:create_zone, zone, server_name}) end - - @spec show_zone(String.t, String.t) :: :ok | {:error, String.t} + @spec show_zone(String.t(), String.t()) :: :ok | {:error, String.t()} @doc """ Show / Retrive info of the specific Zone """ @@ -51,8 +50,7 @@ defmodule PowerDNSex do call({:show_zone, zone, server_name}) end - - @spec delete_zone(String.t, String.t) :: :ok | {:error, String.t} + @spec delete_zone(String.t(), String.t()) :: :ok | {:error, String.t()} @doc """ Delete specific Zone on PowerDNS """ @@ -64,7 +62,7 @@ defmodule PowerDNSex do # Records # ########### - @spec create_record(Zone.t, struct) :: :ok | {:error, String.t} + @spec create_record(Zone.t(), struct) :: :ok | {:error, String.t()} @doc """ Create a new Record for the given Zone """ @@ -72,7 +70,7 @@ defmodule PowerDNSex do call({:create_record, zone, rrset_attrs}) end - @spec show_record(String.t, struct) :: :ok | {:error, String.t} + @spec show_record(String.t(), struct) :: :ok | {:error, String.t()} @doc """ Show / Retrive info of the specific Record of the given Zone name """ @@ -80,7 +78,7 @@ defmodule PowerDNSex do call({:show_record, zone_name, rrset_attrs}) end - @spec update_record(Zone.t, struct) :: :ok | {:error, String.t} + @spec update_record(Zone.t(), struct) :: :ok | {:error, String.t()} @doc """ Update Record of the given Zone """ @@ -88,7 +86,7 @@ defmodule PowerDNSex do call({:update_record, zone, rrset_attrs}) end - @spec delete_record(Zone.t, struct) :: :ok | {:error, String.t} + @spec delete_record(Zone.t(), struct) :: :ok | {:error, String.t()} @doc """ Delete specific Record of given Zone """ @@ -101,5 +99,4 @@ defmodule PowerDNSex do ########### defp call(params), do: GenServer.call(@name, params) - end diff --git a/lib/powerdnsex/config.ex b/lib/powerdnsex/config.ex index 0d97cb2..34d5889 100644 --- a/lib/powerdnsex/config.ex +++ b/lib/powerdnsex/config.ex @@ -5,22 +5,22 @@ defmodule PowerDNSex.Config do alias PowerDNSex.Config def data do - set_attr_value = &(Map.put(&2, &1, get_key(&1))) + set_attr_value = &Map.put(&2, &1, get_key(&1)) %Config{} - |> Map.from_struct - |> Map.keys + |> Map.from_struct() + |> Map.keys() |> Enum.reduce(%Config{}, set_attr_value) end def powerdns_url do - url = data.url - if String.ends_with?(url, "/"), do: url, else: url <> "/" + url = data().url + if String.ends_with?(url, "/"), do: url, else: url <> "/" end - def powerdns_token, do: data.token + def powerdns_token, do: data().token - def valid?(), do: powerdns_url && powerdns_token + def valid?(), do: powerdns_url() && powerdns_token() ### # Private @@ -28,8 +28,12 @@ defmodule PowerDNSex.Config do defp get_key(key) do case Application.fetch_env(:powerdnsex, key) do - {:ok, {:system, env_var_name}} -> System.get_env(env_var_name) - {:ok, value} -> value + {:ok, {:system, env_var_name}} -> + System.get_env(env_var_name) + + {:ok, value} -> + value + _ -> raise "[PowerDNSex] PowerDNS #{Atom.to_string(key)} not configured." end diff --git a/lib/powerdnsex/converter.ex b/lib/powerdnsex/converter.ex index 507c119..8f8639e 100644 --- a/lib/powerdnsex/converter.ex +++ b/lib/powerdnsex/converter.ex @@ -7,9 +7,12 @@ defmodule PowerDNSex.Converter do for {key, value} <- struct, into: %{} do n_key = if is_binary(key), do: String.to_atom(key), else: key - n_value = if is_map(value) or is_list(value) do - keys_to_atom(value) - else value end + n_value = + if is_map(value) or is_list(value) do + keys_to_atom(value) + else + value + end {n_key, n_value} end diff --git a/lib/powerdnsex/gen_server/server.ex b/lib/powerdnsex/gen_server/server.ex index 3b24503..a0bb7d8 100644 --- a/lib/powerdnsex/gen_server/server.ex +++ b/lib/powerdnsex/gen_server/server.ex @@ -2,7 +2,11 @@ defmodule PowerDNSex.Server do use GenServer alias PowerDNSex.Managers.{ZonesManager, RecordsManager} - alias PowerDNSex.{Models.Zone, Converter} + alias PowerDNSex.Converter + + def init(args) do + {:ok, args} + end def start_link(name) do GenServer.start_link(__MODULE__, :ok, name: name) diff --git a/lib/powerdnsex/http_client.ex b/lib/powerdnsex/http_client.ex index 0a242b5..13e5023 100644 --- a/lib/powerdnsex/http_client.ex +++ b/lib/powerdnsex/http_client.ex @@ -1,5 +1,5 @@ defmodule PowerDNSex.HttpClient do - @moduledoc""" + @moduledoc """ Client to do http requests for PowerDns API """ @@ -7,10 +7,10 @@ defmodule PowerDNSex.HttpClient do alias PowerDNSex.Config - def process_url(url), do: Config.powerdns_url <> url + 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) + def process_request_headers(headers) do + custom = ["X-API-Key": Config.powerdns_token()] + Keyword.merge(headers, custom) end end diff --git a/lib/powerdnsex/managers/records_manager.ex b/lib/powerdnsex/managers/records_manager.ex index 9b6a96f..f2ef6b5 100644 --- a/lib/powerdnsex/managers/records_manager.ex +++ b/lib/powerdnsex/managers/records_manager.ex @@ -7,7 +7,6 @@ defmodule PowerDNSex.Managers.RecordsManager do alias PowerDNSex.Managers.ZonesManager alias HTTPoison.Response - def create(%Zone{} = zone, %{} = rrset_attrs) do rrset_attrs = Map.merge(rrset_attrs, %{changetype: "REPLACE"}) patch(zone, rrset_attrs) @@ -45,9 +44,12 @@ defmodule PowerDNSex.Managers.RecordsManager do defp process_request_response(%Response{body: body, status_code: status}) do case status do - s when s == 204 -> :ok + s when s == 204 -> + :ok + s when s < 300 -> :ok + s when s >= 300 -> error = Poison.decode!(body, as: %Error{}) {:error, %{error | http_status_code: s}} @@ -60,7 +62,7 @@ defmodule PowerDNSex.Managers.RecordsManager do defp patch(%Zone{} = zone, %RRSet{} = rrset) do rrset_body = RRSet.as_body(rrset) - Logger.info "Request to [#{zone.name}] with params [#{rrset_body}]" + Logger.info("Request to [#{zone.name}] with params [#{rrset_body}]") zone.url |> HttpClient.patch!(rrset_body) diff --git a/lib/powerdnsex/managers/zones_manager.ex b/lib/powerdnsex/managers/zones_manager.ex index c7ec1ab..23bab1d 100644 --- a/lib/powerdnsex/managers/zones_manager.ex +++ b/lib/powerdnsex/managers/zones_manager.ex @@ -1,5 +1,4 @@ defmodule PowerDNSex.Managers.ZonesManager do - @default_server "localhost" alias PowerDNSex.HttpClient @@ -15,19 +14,17 @@ defmodule PowerDNSex.Managers.ZonesManager do def show(zone_name, server_name \\ @default_server) when is_bitstring(zone_name) do - server_name |> zone_path(zone_name) - |> HttpClient.get! + |> HttpClient.get!() |> process_request_response end def delete(zone_name, server_name \\ @default_server) when is_bitstring(zone_name) do - server_name |> zone_path(zone_name) - |> HttpClient.delete! + |> HttpClient.delete!() |> process_request_response end @@ -45,20 +42,25 @@ defmodule PowerDNSex.Managers.ZonesManager do defp process_request_response(%Response{body: body, status_code: status}) do case status do - s when s == 204 -> {:ok, %{}} - s when s < 300 -> {:ok, decode_body(body)} + s when s == 204 -> + {:ok, %{}} + + s when s < 300 -> + {:ok, decode_body(body)} + s when s == 500 -> {:error, %Error{error: "Internal Server Error", http_status_code: s}} + s when s >= 300 -> - error = %{Poison.decode!(body,as: %Error{}) | http_status_code: s} + error = %{Poison.decode!(body, as: %Error{}) | http_status_code: s} {:error, error} end end defp decode_body(body) do - zone = body - |> Poison.decode!(as: %Zone{rrsets: - [%ResourceRecordSet{records: [%Record{}]}]}) + zone = + body + |> Poison.decode!(as: %Zone{rrsets: [%ResourceRecordSet{records: [%Record{}]}]}) nameservers = ResourceRecordSet.nameservers(zone.rrsets) Map.put(zone, :nameservers, nameservers) diff --git a/lib/powerdnsex/models/error.ex b/lib/powerdnsex/models/error.ex index b4397df..c1626f0 100644 --- a/lib/powerdnsex/models/error.ex +++ b/lib/powerdnsex/models/error.ex @@ -1,5 +1,5 @@ defmodule PowerDNSex.Models.Error do defstruct [:error, :http_status_code] - @type t :: %__MODULE__{error: String.t} + @type t :: %__MODULE__{error: String.t()} end diff --git a/lib/powerdnsex/models/record.ex b/lib/powerdnsex/models/record.ex index ed0e327..b73cd98 100644 --- a/lib/powerdnsex/models/record.ex +++ b/lib/powerdnsex/models/record.ex @@ -20,8 +20,8 @@ defmodule PowerDNSex.Models.Record do end def find(records, attrs) when is_list(records) do - Enum.find(records, fn(record) -> - Enum.all?(attrs, fn({attr, attr_value}) -> + Enum.find(records, fn record -> + Enum.all?(attrs, fn {attr, attr_value} -> Map.get(record, attr) == attr_value end) end) diff --git a/lib/powerdnsex/models/resource_record_set.ex b/lib/powerdnsex/models/resource_record_set.ex index 1a410b1..dbb90b3 100644 --- a/lib/powerdnsex/models/resource_record_set.ex +++ b/lib/powerdnsex/models/resource_record_set.ex @@ -1,5 +1,4 @@ defmodule PowerDNSex.Models.ResourceRecordSet do - alias PowerDNSex.Models.Record defstruct [:name, :type, :ttl, :records, :changetype] @@ -10,21 +9,23 @@ defmodule PowerDNSex.Models.ResourceRecordSet do end def as_body(%__MODULE__{} = rrset) do - %{rrsets: [ - %{ - name: rrset.name, - type: rrset.type, - ttl: rrset.ttl, - changetype: rrset.changetype, - records: Record.as_body(rrset.records) - } - ]} - |> Poison.encode! + %{ + rrsets: [ + %{ + name: rrset.name, + type: rrset.type, + ttl: rrset.ttl, + changetype: rrset.changetype, + records: Record.as_body(rrset.records) + } + ] + } + |> Poison.encode!() end def find(rrsets, %{} = attrs) when is_list(rrsets) do - Enum.find(rrsets, fn(rrset) -> - Enum.all?(attrs, fn({attr, attr_value}) -> + 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 @@ -35,23 +36,26 @@ defmodule PowerDNSex.Models.ResourceRecordSet do end def update(%__MODULE__{} = rrset, %{} = new_attrs) do - Enum.reduce(@permited_attrs, rrset, fn(attr_name, rrset) -> - case Map.fetch(new_attrs, attr_name) do - {:ok, new_value} -> - if attr_name == :records do - new_value = Record.build(new_value) - end - %{rrset | attr_name => new_value} - _ -> rrset - end - end) + Enum.reduce(@permited_attrs, rrset, fn attr_name, rrset -> + case {attr_name, Map.fetch(new_attrs, attr_name)} do + {:records, {:ok, new_value}} -> + %{rrset | attr_name => Record.build(new_value)} + + {_, {:ok, new_value}} -> + %{rrset | attr_name => new_value} + + _ -> + rrset + end + end) end def nameservers(rrsets) do - rrset = Enum.find(rrsets, fn(rrset) -> rrset.type == "NS" end) - nameservers = case rrset do + rrset = Enum.find(rrsets, fn rrset -> rrset.type == "NS" end) + + case rrset do nil -> [] - _ -> Enum.map(rrset.records, &(&1.content) ) + _ -> Enum.map(rrset.records, & &1.content) end end @@ -62,10 +66,11 @@ defmodule PowerDNSex.Models.ResourceRecordSet do defp set_attrs(rrset, attr_name, attrs) do if Map.has_key?(attrs, attr_name) do - attr_value = case attr_name do - :records -> Record.build(Map.fetch!(attrs, attr_name)) - _ -> Map.fetch!(attrs, attr_name) - end + attr_value = + case attr_name do + :records -> Record.build(Map.fetch!(attrs, attr_name)) + _ -> Map.fetch!(attrs, attr_name) + end %{rrset | attr_name => attr_value} else @@ -80,7 +85,7 @@ defmodule PowerDNSex.Models.ResourceRecordSet do defp build_rrset(rrset_attrs) do %__MODULE__{} - |> Map.keys - |> Enum.reduce(%__MODULE__{}, &(set_attrs(&2, &1, rrset_attrs))) + |> Map.keys() + |> Enum.reduce(%__MODULE__{}, &set_attrs(&2, &1, rrset_attrs)) end end diff --git a/lib/powerdnsex/models/zone.ex b/lib/powerdnsex/models/zone.ex index 8620443..96089e0 100644 --- a/lib/powerdnsex/models/zone.ex +++ b/lib/powerdnsex/models/zone.ex @@ -6,15 +6,26 @@ defmodule PowerDNSex.Models.Zone do @body_attrs ~w(account dns kind masters name nameservers records serial soa_edit soa_edit_api)a - defstruct name: nil, kind: "Native", masters: [], nameservers: [], rrsets: [], - account: nil, comments: [], dnssec: false, id: nil, last_check: 0, - notified_serial: 0, serial: nil, soa_edit: "", soa_edit_api: "", + defstruct name: nil, + kind: "Native", + masters: [], + nameservers: [], + rrsets: [], + account: nil, + comments: [], + dnssec: false, + id: nil, + last_check: 0, + notified_serial: 0, + serial: nil, + soa_edit: "", + soa_edit_api: "", url: nil @type t :: %__MODULE__{} def as_body(%__MODULE__{} = zone) do - get_valid_attrs = fn({attr, value}, body) -> + get_valid_attrs = fn {attr, value}, body -> if Enum.member?(@body_attrs, attr) do Map.merge(body, %{attr => value}) else @@ -23,8 +34,8 @@ defmodule PowerDNSex.Models.Zone do end zone - |> Map.from_struct + |> Map.from_struct() |> Enum.reduce(%{}, get_valid_attrs) - |> Poison.encode! + |> Poison.encode!() end end diff --git a/mix.exs b/mix.exs index ee0a091..94fe8a5 100644 --- a/mix.exs +++ b/mix.exs @@ -2,14 +2,16 @@ defmodule PowerDNSex.Mixfile do use Mix.Project def project do - [app: :powerdnsex, - version: "0.1.0", - elixir: "~> 1.3", - description: description(), - package: package(), - build_embedded: Mix.env == :prod, - start_permanent: Mix.env == :prod, - deps: deps()] + [ + app: :powerdnsex, + version: "0.2.0", + elixir: "~> 1.6", + description: description(), + package: package(), + build_embedded: Mix.env() == :prod, + start_permanent: Mix.env() == :prod, + deps: deps() + ] end def application do @@ -17,9 +19,7 @@ defmodule PowerDNSex.Mixfile do end defp deps do - [{:httpoison, "~> 0.13.0"}, - {:poison, "~> 2.2"}, - {:exvcr, "~> 0.9.1", only: :test}] + [{:httpoison, "~> 1.5.0"}, {:poison, "~> 4.0.1"}, {:exvcr, "~> 0.10.3", only: :test}] end defp description do @@ -29,9 +29,10 @@ defmodule PowerDNSex.Mixfile do end defp package do - [maintainers: ["Rodrigo Coutinho"], - licenses: ["MIT"], - links: %{"GitHub" => "https://github.com/digaoddc/power_dnsex"} + [ + maintainers: ["Lindolfo Rodrigues"], + licenses: ["MIT"], + links: %{"GitHub" => "https://github.com/locaweb/power_dnsex"} ] end end diff --git a/mix.lock b/mix.lock index 4d9c60a..706f8df 100644 --- a/mix.lock +++ b/mix.lock @@ -1,14 +1,17 @@ -%{"certifi": {:hex, :certifi, "2.0.0", "a0c0e475107135f76b8c1d5bc7efb33cd3815cb3cf3dea7aefdd174dabead064", [:rebar3], [], "hexpm"}, +%{ + "certifi": {:hex, :certifi, "2.4.2", "75424ff0f3baaccfd34b1214184b6ef616d89e420b258bb0a5ea7d7bc628f7f0", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"}, "exactor": {:hex, :exactor, "2.2.4", "5efb4ddeb2c48d9a1d7c9b465a6fffdd82300eb9618ece5d34c3334d5d7245b1", [:mix], [], "hexpm"}, "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, - "exvcr": {:hex, :exvcr, "0.9.1", "31e3936a790a14bf56b31b6b276577076a5ef8afd9b2d53ba3ff8bb647d45613", [:mix], [{:exactor, "~> 2.2", [hex: :exactor, repo: "hexpm", optional: false]}, {:exjsx, "~> 4.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:httpoison, "~> 0.13", [hex: :httpoison, repo: "hexpm", optional: true]}, {:httpotion, "~> 3.0", [hex: :httpotion, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:meck, "~> 0.8.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"}, - "hackney": {:hex, :hackney, "1.10.1", "c38d0ca52ea80254936a32c45bb7eb414e7a96a521b4ce76d00a69753b157f21", [:rebar3], [{:certifi, "2.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, - "httpoison": {:hex, :httpoison, "0.13.0", "bfaf44d9f133a6599886720f3937a7699466d23bb0cd7a88b6ba011f53c6f562", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, - "idna": {:hex, :idna, "5.1.0", "d72b4effeb324ad5da3cab1767cb16b17939004e789d8c0ad5b70f3cea20c89a", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, + "exvcr": {:hex, :exvcr, "0.10.3", "1ae3b97560430acfa88ebc737c85b2b7a9dbacd8a2b26789a19718b51ae3522c", [:mix], [{:exactor, "~> 2.2", [hex: :exactor, repo: "hexpm", optional: false]}, {:exjsx, "~> 4.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: true]}, {:httpotion, "~> 3.1", [hex: :httpotion, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:meck, "~> 0.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"}, + "hackney": {:hex, :hackney, "1.15.0", "287a5d2304d516f63e56c469511c42b016423bcb167e61b611f6bad47e3ca60e", [:rebar3], [{:certifi, "2.4.2", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, + "httpoison": {:hex, :httpoison, "1.5.0", "71ae9f304bdf7f00e9cd1823f275c955bdfc68282bc5eb5c85c3a9ade865d68e", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, + "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, "jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], [], "hexpm"}, - "meck": {:hex, :meck, "0.8.9", "64c5c0bd8bcca3a180b44196265c8ed7594e16bcc845d0698ec6b4e577f48188", [:rebar3], [], "hexpm"}, + "meck": {:hex, :meck, "0.8.13", "ffedb39f99b0b99703b8601c6f17c7f76313ee12de6b646e671e3188401f7866", [:rebar3], [], "hexpm"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"}, - "poison": {:hex, :poison, "2.2.0", "4763b69a8a77bd77d26f477d196428b741261a761257ff1cf92753a0d4d24a63", [:mix], [], "hexpm"}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"}, - "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"}} + "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"}, + "poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"}, +} diff --git a/script/clean b/script/clean new file mode 100755 index 0000000..a0ac4b3 --- /dev/null +++ b/script/clean @@ -0,0 +1,3 @@ +#!/bin/bash +docker-compose run --rm web rm -fr _build deps +docker-compose down diff --git a/script/common.sh b/script/common.sh new file mode 100644 index 0000000..dffe136 --- /dev/null +++ b/script/common.sh @@ -0,0 +1,8 @@ +function power_dnsex_env { + local envs=$(env | egrep '^POWER_DNSEX_' | sed 's/^/ -e /') + local test_env=$( [[ -n "${BUILD_TAG}" ]] && printf " -e MIX_ENV=test" ) + printf "%s " "$envs $test_env" | xargs printf " %s" +} + +export WORKDIR="$(dirname "${BASH_SOURCE[0]}")/.." +export DOCKER_COMPOSE="docker-compose -f $WORKDIR/docker-compose.yml" diff --git a/script/coverage b/script/coverage new file mode 100755 index 0000000..4c5cb0f --- /dev/null +++ b/script/coverage @@ -0,0 +1,5 @@ +#!/bin/bash -xe + +source "$(dirname "${BASH_SOURCE[0]}")/common.sh" + +$DOCKER_COMPOSE run -T -e MIX_ENV=test $(power_dnsex_env) --rm web bash -c "mix coveralls.html - PowerDNSex.Config.powerdns_token + PowerDNSex.Config.powerdns_token() end end end @@ -39,20 +38,21 @@ defmodule PowerDNSex.ConfigTest do env_url = "https://env-powerdns.test/" System.put_env("POWERDNS_URL", env_url) Application.put_env(:powerdnsex, :url, {:system, "POWERDNS_URL"}) - assert PowerDNSex.Config.powerdns_url == env_url + assert PowerDNSex.Config.powerdns_url() == env_url end @tag :configs test "using application config" do - assert PowerDNSex.Config.powerdns_url == Config.url <> "/" + assert PowerDNSex.Config.powerdns_url() == Config.url() <> "/" end @tag :configs test "given none url config" do Application.delete_env(:powerdnsex, :url) expected_error = "[PowerDNSex] PowerDNS url not configured." + assert_raise RuntimeError, expected_error, fn -> - PowerDNSex.Config.powerdns_url + PowerDNSex.Config.powerdns_url() end end end diff --git a/test/lib/powerdnsex/managers/records_manager_test.exs b/test/lib/powerdnsex/managers/records_manager_test.exs index 4c83b40..7de02ab 100644 --- a/test/lib/powerdnsex/managers/records_manager_test.exs +++ b/test/lib/powerdnsex/managers/records_manager_test.exs @@ -1,5 +1,4 @@ defmodule PowerDNSex.Managers.RecordsManagerTest do - use ExUnit.Case, async: false use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney @@ -17,7 +16,7 @@ defmodule PowerDNSex.Managers.RecordsManagerTest do @valid_zone %Zone{ name: "my-domain.art.", - url: "api/v1/servers/localhost/zones/my-domain.art.", + url: "api/v1/servers/localhost/zones/my-domain.art.", rrsets: [@record] } @@ -50,19 +49,23 @@ defmodule PowerDNSex.Managers.RecordsManagerTest do } setup do - Config.set_url - Config.set_token + Config.set_url() + Config.set_token() + + ExVCR.Config.cassette_library_dir( + "test/support/cassettes", + "test/support/custom_cassettes" + ) - ExVCR.Config.cassette_library_dir("test/support/cassettes", - "test/support/custom_cassettes") - HTTPoison.start + HTTPoison.start() end describe "create/2" do @tag :records_manager_create test "exception given empty zones url" do raise_msg = "[Records Manager] Zone URL attribute is empty!" - assert_raise RuntimeError, raise_msg, fn() -> + + assert_raise RuntimeError, raise_msg, fn -> RecordsManager.create(%Zone{}, %Record{}) end end @@ -80,9 +83,7 @@ defmodule PowerDNSex.Managers.RecordsManagerTest do test "content given attrs of a valid record" do use_cassette "records_manager/show/success" do zone_name = @valid_zone.name - attrs = %{name: "new-record.#{zone_name}", - type: "A", - content: "127.0.0.1"} + attrs = %{name: "new-record.#{zone_name}", type: "A", content: "127.0.0.1"} record = RecordsManager.show(zone_name, attrs) assert record.name == attrs.name diff --git a/test/lib/powerdnsex/managers/zones_manager_test.exs b/test/lib/powerdnsex/managers/zones_manager_test.exs index 9c011e9..1b4982e 100644 --- a/test/lib/powerdnsex/managers/zones_manager_test.exs +++ b/test/lib/powerdnsex/managers/zones_manager_test.exs @@ -1,5 +1,4 @@ defmodule PowerDNSex.Managers.ZonesManagerTest do - use ExUnit.Case, async: false use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney @@ -11,9 +10,11 @@ defmodule PowerDNSex.Managers.ZonesManagerTest do @invalid_not_canonical %Zone{name: "not-canonical-domain.tst"} @unknown_name "it-will-never-exist.on.the.art." - @valid_zone_test %Zone{name: "my-domain.art.", - serial: 2_016_060_601, - comments: ["Test comment"] } + @valid_zone_test %Zone{ + name: "my-domain.art.", + serial: 2_016_060_601, + comments: ["Test comment"] + } @expected_rrset [ %RRSet{ @@ -21,10 +22,13 @@ defmodule PowerDNSex.Managers.ZonesManagerTest do ttl: 3600, type: "SOA", records: [ - %Record{content: "a.misconfigured.powerdns.server. " <> - "hostmaster.my-domain.art. " <> - "2016060601 10800 3600 604800 3600", - disabled: false} + %Record{ + content: + "a.misconfigured.powerdns.server. " <> + "hostmaster.my-domain.art. " <> + "2016060601 10800 3600 604800 3600", + disabled: false + } ] }, %RRSet{ @@ -32,27 +36,31 @@ defmodule PowerDNSex.Managers.ZonesManagerTest do ttl: 3600, type: "NS", records: [ - %Record{content: "ns1.domain.com", - disabled: false} + %Record{content: "ns1.domain.com", disabled: false} ] } ] - @expected_zone %Zone{name: "my-domain.art.", - id: "my-domain.art.", - account: "", - serial: 2_016_060_601, - url: "api/v1/servers/localhost/zones/my-domain.art.", - nameservers: ["ns1.domain.com"], - rrsets: @expected_rrset} + @expected_zone %Zone{ + name: "my-domain.art.", + id: "my-domain.art.", + account: "", + serial: 2_016_060_601, + url: "api/v1/servers/localhost/zones/my-domain.art.", + nameservers: ["ns1.domain.com"], + rrsets: @expected_rrset + } setup do - Config.set_url - Config.set_token + Config.set_url() + Config.set_token() + + ExVCR.Config.cassette_library_dir( + "test/support/cassettes", + "test/support/custom_cassettes" + ) - ExVCR.Config.cassette_library_dir("test/support/cassettes", - "test/support/custom_cassettes") - HTTPoison.start + HTTPoison.start() end describe "ZoneManager.create/2" do diff --git a/test/lib/powerdnsex/models/resource_record_set_test.exs b/test/lib/powerdnsex/models/resource_record_set_test.exs index 9533beb..41838cc 100644 --- a/test/lib/powerdnsex/models/resource_record_set_test.exs +++ b/test/lib/powerdnsex/models/resource_record_set_test.exs @@ -1,5 +1,4 @@ defmodule PowerDNSex.Models.ResourceRecordSetTest do - use ExUnit.Case, async: true alias PowerDNSex.Models.{Record} @@ -10,25 +9,22 @@ defmodule PowerDNSex.Models.ResourceRecordSetTest do @domain "my-domain.art." - @record_ns %RRSet { + @record_ns %RRSet{ name: "my-domain.art.", ttl: 3600, type: "NS", records: [ - %Record{content: @ns_content, - disabled: false}, - %Record{content: @ns2_content, - disabled: false} + %Record{content: @ns_content, disabled: false}, + %Record{content: @ns2_content, disabled: false} ] } - @record_a %RRSet { + @record_a %RRSet{ name: "store.my-domain.art.", ttl: 3600, type: "A", records: [ - %Record{content: "182.23.2.3", - disabled: false} + %Record{content: "182.23.2.3", disabled: false} ] } @@ -49,11 +45,21 @@ defmodule PowerDNSex.Models.ResourceRecordSetTest do describe "build/1" do test "build a record" do - raw_rrset = %{name: @domain, type: 'A', ttl: 3600, records: [ %{content: "192.168.0.1", disabled: false} ] } - rrset = %RRSet{changetype: nil, - name: "my-domain.art.", - records: [%PowerDNSex.Models.Record{content: "192.168.0.1", - disabled: false}], ttl: 3600, type: 'A'} + raw_rrset = %{ + name: @domain, + type: 'A', + ttl: 3600, + records: [%{content: "192.168.0.1", disabled: false}] + } + + rrset = %RRSet{ + changetype: nil, + name: "my-domain.art.", + records: [%PowerDNSex.Models.Record{content: "192.168.0.1", disabled: false}], + ttl: 3600, + type: 'A' + } + assert RRSet.build(raw_rrset) == rrset end end @@ -70,20 +76,22 @@ defmodule PowerDNSex.Models.ResourceRecordSetTest do describe "update/2" do test "update passing all attributes" do - new_attrs = %{name: "page.my-domain.art.", - records: [%{content: "192.168.0.1", disabled: false}], - ttl: "3600", type: "A"} - - new_record = %PowerDNSex.Models.ResourceRecordSet{changetype: nil, - name: "store.my-domain.art.", - records: [ - %PowerDNSex.Models.Record{ - content: "192.168.0.1", - disabled: false}], - type: "A", - ttl: "3600"} - - assert RRSet.update(@record_a, new_attrs) == new_record + new_attrs = %{ + name: "page.my-domain.art.", + records: [%{content: "192.168.0.1", disabled: false}], + ttl: "3600", + type: "A" + } + + new_record = %PowerDNSex.Models.ResourceRecordSet{ + changetype: nil, + name: "store.my-domain.art.", + records: [%PowerDNSex.Models.Record{content: "192.168.0.1", disabled: false}], + type: "A", + ttl: "3600" + } + + assert RRSet.update(@record_a, new_attrs) == new_record end end end diff --git a/test/lib/powerdnsex/models/zone_test.exs b/test/lib/powerdnsex/models/zone_test.exs index e69de29..8b13789 100644 --- a/test/lib/powerdnsex/models/zone_test.exs +++ b/test/lib/powerdnsex/models/zone_test.exs @@ -0,0 +1 @@ + diff --git a/test/lib/powerdnsex/powerdnsex_test.exs b/test/lib/powerdnsex/powerdnsex_test.exs index 10f8e7a..92e7f91 100644 --- a/test/lib/powerdnsex/powerdnsex_test.exs +++ b/test/lib/powerdnsex/powerdnsex_test.exs @@ -1,14 +1,16 @@ defmodule PowerDNSexTest do - use ExUnit.Case, async: false use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney setup do - Config.set_url - Config.set_token + Config.set_url() + Config.set_token() + + ExVCR.Config.cassette_library_dir( + "test/support/cassettes", + "test/support/custom_cassettes" + ) - ExVCR.Config.cassette_library_dir("test/support/cassettes", - "test/support/custom_cassettes") - HTTPoison.start + HTTPoison.start() end end diff --git a/test/support/fake_config.exs b/test/support/fake_config.exs index 0c27d93..c8f4f60 100644 --- a/test/support/fake_config.exs +++ b/test/support/fake_config.exs @@ -2,7 +2,6 @@ defmodule PowerDNSex.FakeConfig do @app_config_token "S3cr37_70k3n" @app_config_url "https://my-powerdns.api" - def set_url, do: Application.put_env(:powerdnsex, :url, @app_config_url) def set_token, do: Application.put_env(:powerdnsex, :token, @app_config_token) diff --git a/test/test_helper.exs b/test/test_helper.exs index 2fc6291..f0625ca 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -2,8 +2,8 @@ ExUnit.start() {:ok, files} = File.ls("./test/support/") -Enum.each files, fn(file) -> +Enum.each(files, fn file -> if String.match?(file, ~r/(.*).exs$/) do - Code.require_file "support/#{file}", __DIR__ + Code.require_file("support/#{file}", __DIR__) end -end +end) -- cgit v1.2.3