Set editorconfig, format whole codebase

This commit is contained in:
Timothée Floure 2022-02-23 17:53:00 +01:00
parent e62aafd172
commit ebcfabdbd2
Signed by: tfloure
GPG key ID: 4502C902C00A1E12
11 changed files with 380 additions and 329 deletions

12
.editorconfig Normal file
View file

@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*.ex]
indent_style = space
indent_size = 2
[*.eex]
indent_style = space
indent_size = 2

View file

@ -6,8 +6,8 @@ defmodule HAHandler do
# Mix is not available in releases, and these things are static # Mix is not available in releases, and these things are static
# anyway (@variables are evaluated at compile time). # anyway (@variables are evaluated at compile time).
@otp_app Mix.Project.config()[:app] @otp_app Mix.Project.config()[:app]
@version Mix.Project.config[:version] @version Mix.Project.config()[:version]
@env Mix.env @env Mix.env()
def http_port, do: Application.get_env(@otp_app, :http_port) def http_port, do: Application.get_env(@otp_app, :http_port)
def haproxy_socket, do: Application.get_env(@otp_app, :haproxy_socket) def haproxy_socket, do: Application.get_env(@otp_app, :haproxy_socket)
@ -26,6 +26,7 @@ defmodule HAHandler do
from: acme_challenge_path() from: acme_challenge_path()
] ]
end end
def assets_static_config() do def assets_static_config() do
[ [
at: "/static", at: "/static",

View file

@ -10,7 +10,8 @@ defmodule HAHandler.Application do
@impl true @impl true
def start(_type, _args) do def start(_type, _args) do
children = [ children = [
{Plug.Cowboy, scheme: :http, plug: HAHandler.Web.Router, options: [port: HAHandler.http_port()]}, {Plug.Cowboy,
scheme: :http, plug: HAHandler.Web.Router, options: [port: HAHandler.http_port()]},
{HAHandler.PGSQL.Supervisor, HAHandler.pgsql_instances()}, {HAHandler.PGSQL.Supervisor, HAHandler.pgsql_instances()},
{HAHandler.Control, []} {HAHandler.Control, []}
] ]

View file

@ -25,7 +25,7 @@ defmodule HAHandler.Control do
# Let's skip the initial startup round so that other components are all up # Let's skip the initial startup round so that other components are all up
# and running. # and running.
Process.send_after self(), :sync, @refresh Process.send_after(self(), :sync, @refresh)
{:ok, state} {:ok, state}
end end
@ -36,9 +36,11 @@ defmodule HAHandler.Control do
# Fetch PGSQL state, make sure HAProxy routes to the master # Fetch PGSQL state, make sure HAProxy routes to the master
# process. # process.
pgsql_state = PGSQL.get_instances() pgsql_state =
PGSQL.get_instances()
|> Enum.map(fn {hostname, pid} = instance -> |> Enum.map(fn {hostname, pid} = instance ->
haproxy_server = HAHandler.pgsql_instances() haproxy_server =
HAHandler.pgsql_instances()
|> Enum.filter(fn opts -> Keyword.get(opts, :hostname) == hostname end) |> Enum.filter(fn opts -> Keyword.get(opts, :hostname) == hostname end)
|> Enum.at(0) |> Enum.at(0)
|> Keyword.get(:haproxy_server) |> Keyword.get(:haproxy_server)
@ -49,7 +51,9 @@ defmodule HAHandler.Control do
pgsql_operation_mode: PGSQL.get_operation_mode(instance) pgsql_operation_mode: PGSQL.get_operation_mode(instance)
} }
end) end)
haproxy_state = HAProxy.get_stats()
haproxy_state =
HAProxy.get_stats()
|> Map.get("Server", []) |> Map.get("Server", [])
|> Enum.filter(fn mapping -> mapping["pxname"] == @haproxy_pgsql_backend end) |> Enum.filter(fn mapping -> mapping["pxname"] == @haproxy_pgsql_backend end)
|> Enum.map(fn mapping -> %{mapping["svname"] => mapping["status"]} end) |> Enum.map(fn mapping -> %{mapping["svname"] => mapping["status"]} end)
@ -61,21 +65,39 @@ defmodule HAHandler.Control do
case {pgsql_instance.pgsql_operation_mode, haproxy_state} do case {pgsql_instance.pgsql_operation_mode, haproxy_state} do
{:primary, "UP"} -> {:primary, "UP"} ->
:noop :noop
{:primary, "MAINT"} -> {:primary, "MAINT"} ->
Logger.info("Enabling routing PGSQL to (now) primary #{pgsql_instance.haproxy_server}.") Logger.info("Enabling routing PGSQL to (now) primary #{pgsql_instance.haproxy_server}.")
HAProxy.set_server(@haproxy_pgsql_backend, pgsql_instance.haproxy_server, "state", "ready")
HAProxy.set_server(
@haproxy_pgsql_backend,
pgsql_instance.haproxy_server,
"state",
"ready"
)
{:secondary, "UP"} -> {:secondary, "UP"} ->
Logger.info("Disabling routing PGSQL to (now) secondary #{pgsql_instance.haproxy_server}.") Logger.info(
HAProxy.set_server(@haproxy_pgsql_backend, pgsql_instance.haproxy_server, "state", "maint") "Disabling routing PGSQL to (now) secondary #{pgsql_instance.haproxy_server}."
)
HAProxy.set_server(
@haproxy_pgsql_backend,
pgsql_instance.haproxy_server,
"state",
"maint"
)
{:secondary, "MAINT"} -> {:secondary, "MAINT"} ->
:noop :noop
unknown -> unknown ->
Logger.warning("Unhandled PGSQL/HAProxy state: #{inspect(unknown)}") Logger.warning("Unhandled PGSQL/HAProxy state: #{inspect(unknown)}")
end end
end end
# Schedule next round. # Schedule next round.
Process.send_after self(), :sync, @refresh Process.send_after(self(), :sync, @refresh)
{:noreply, state} {:noreply, state}
end end

View file

@ -33,13 +33,15 @@ defmodule HAHandler.HAProxy do
# run out - which will block all operations. # run out - which will block all operations.
close_socket(fd) close_socket(fd)
data data
{:error, err} -> {:error, err} ->
{:error, err} {:error, err}
end end
end end
defp extract_stats(data) do defp extract_stats(data) do
extracted = for entry <- data do extracted =
for entry <- data do
for mapping <- entry do for mapping <- entry do
case mapping do case mapping do
%{ %{
@ -47,9 +49,10 @@ defmodule HAHandler.HAProxy do
"proxyId" => proxy_id, "proxyId" => proxy_id,
"objType" => type, "objType" => type,
"field" => %{"name" => name}, "field" => %{"name" => name},
"value" => %{"value" => value}, "value" => %{"value" => value}
} -> } ->
%{:id => id, :proxy_id => proxy_id, :type => type, :field => name, :value => value} %{:id => id, :proxy_id => proxy_id, :type => type, :field => name, :value => value}
_ -> _ ->
nil nil
end end
@ -62,18 +65,14 @@ defmodule HAHandler.HAProxy do
fn mapping -> {mapping.type, mapping.id, mapping.proxy_id} end, fn mapping -> {mapping.type, mapping.id, mapping.proxy_id} end,
fn mapping -> %{mapping.field => mapping.value} end fn mapping -> %{mapping.field => mapping.value} end
) )
|> Enum.map( |> Enum.map(fn {{type, id, proxy_id}, grouped_mappings} ->
fn {{type, id, proxy_id}, grouped_mappings} ->
grouped_mappings grouped_mappings
|> Enum.reduce(fn l, r -> Map.merge(l, r) end) |> Enum.reduce(fn l, r -> Map.merge(l, r) end)
|> Map.put("type", type) |> Map.put("type", type)
|> Map.put("id", id) |> Map.put("id", id)
|> Map.put("proxy_id", proxy_id) |> Map.put("proxy_id", proxy_id)
end end)
) |> Enum.group_by(fn entry -> Map.get(entry, "type") end)
|> Enum.group_by(
fn entry -> Map.get(entry, "type") end
)
end end
@doc """ @doc """
@ -81,7 +80,8 @@ defmodule HAHandler.HAProxy do
a list of Maps. a list of Maps.
""" """
def get_stats(opts \\ []) def get_stats(opts \\ [])
def get_stats([hide_error: true]) do
def get_stats(hide_error: true) do
case get_stats() do case get_stats() do
{:error, _err} -> {:error, _err} ->
%{ %{
@ -89,9 +89,12 @@ defmodule HAHandler.HAProxy do
"Backend" => %{}, "Backend" => %{},
"Server" => %{} "Server" => %{}
} }
stats -> stats
stats ->
stats
end end
end end
def get_stats(_opts) do def get_stats(_opts) do
case execute("show stat json") do case execute("show stat json") do
{:ok, raw} -> {:ok, raw} ->
@ -117,8 +120,10 @@ defmodule HAHandler.HAProxy do
case execute("set server #{backend}/#{server} #{key} #{value}") do case execute("set server #{backend}/#{server} #{key} #{value}") do
{:ok, ""} -> {:ok, ""} ->
:ok :ok
{:ok, err} -> {:ok, err} ->
{:error, err} {:error, err}
{:error, err} -> {:error, err} ->
{:error, err} {:error, err}
end end

View file

@ -5,6 +5,7 @@ defmodule HAHandler.PGSQL do
def get_instances() do def get_instances() do
watchers = Supervisor.which_children(@supervisor) watchers = Supervisor.which_children(@supervisor)
for {hostname, pid, _type, _modules} <- watchers do for {hostname, pid, _type, _modules} <- watchers do
{hostname, pid} {hostname, pid}
end end
@ -13,13 +14,17 @@ defmodule HAHandler.PGSQL do
def get_version({hostname, pid}) do def get_version({hostname, pid}) do
case GenServer.call(pid, {:execute, @version_query, []}) do case GenServer.call(pid, {:execute, @version_query, []}) do
{:ok, %Postgrex.Result{rows: [[raw_version_string]]}} -> {:ok, %Postgrex.Result{rows: [[raw_version_string]]}} ->
version = case Regex.run(~r/^PostgreSQL (\d+\.\d+)/, raw_version_string) do version =
case Regex.run(~r/^PostgreSQL (\d+\.\d+)/, raw_version_string) do
[_, version_number] -> version_number [_, version_number] -> version_number
_ -> "unknown" _ -> "unknown"
end end
%{hostname: hostname, version: version, status: "up"} %{hostname: hostname, version: version, status: "up"}
{:error, %DBConnection.ConnectionError{message: _msg, reason: err}} -> {:error, %DBConnection.ConnectionError{message: _msg, reason: err}} ->
%{hostname: hostname, version: "unknown", status: err} %{hostname: hostname, version: "unknown", status: err}
_ -> _ ->
%{hostname: hostname, version: "unknown", status: :unknown} %{hostname: hostname, version: "unknown", status: :unknown}
end end
@ -29,8 +34,10 @@ defmodule HAHandler.PGSQL do
case GenServer.call(pid, {:execute, @is_in_recovery_query, []}) do case GenServer.call(pid, {:execute, @is_in_recovery_query, []}) do
{:ok, %Postgrex.Result{rows: [[false]]}} -> {:ok, %Postgrex.Result{rows: [[false]]}} ->
:primary :primary
{:ok, %Postgrex.Result{rows: [[true]]}} -> {:ok, %Postgrex.Result{rows: [[true]]}} ->
:secondary :secondary
_ -> _ ->
:unknown :unknown
end end

View file

@ -9,7 +9,8 @@ defmodule HAHandler.PGSQL.Supervisor do
@impl true @impl true
def init(instances) do def init(instances) do
children = Enum.map(instances, fn conf -> children =
Enum.map(instances, fn conf ->
%{ %{
id: Keyword.get(conf, :hostname), id: Keyword.get(conf, :hostname),
start: {PGSQLWatcher, :start_link, [conf]} start: {PGSQLWatcher, :start_link, [conf]}

View file

@ -4,9 +4,7 @@ defmodule HAHandler.Web.Controller do
alias HAHandler.{HAProxy, PGSQL} alias HAHandler.{HAProxy, PGSQL}
@template_dir "lib/ha_handler/web/templates" @template_dir "lib/ha_handler/web/templates"
@index_template EEx.compile_file( @index_template EEx.compile_file(Path.join(@template_dir, "index.html.eex"))
Path.join(@template_dir, "index.html.eex")
)
defp render(conn, template, assigns) do defp render(conn, template, assigns) do
{body, _binding} = Code.eval_quoted(template, assigns) {body, _binding} = Code.eval_quoted(template, assigns)
@ -17,9 +15,9 @@ defmodule HAHandler.Web.Controller do
end end
def index(conn) do def index(conn) do
{:ok, hostname} = :net_adm.dns_hostname(:net_adm.localhost) {:ok, hostname} = :net_adm.dns_hostname(:net_adm.localhost())
haproxy_stats = HAProxy.get_stats([hide_error: true]) haproxy_stats = HAProxy.get_stats(hide_error: true)
pgsql_stats = PGSQL.get_stats() pgsql_stats = PGSQL.get_stats()
assigns = [ assigns = [
@ -30,6 +28,7 @@ defmodule HAHandler.Web.Controller do
version: HAHandler.version(), version: HAHandler.version(),
env: HAHandler.env() env: HAHandler.env()
] ]
render(conn, @index_template, assigns) render(conn, @index_template, assigns)
end end
end end

View file

@ -13,21 +13,24 @@ defmodule HAHandler.Web.Router do
# Note for plugs: oder is important, as a plug may stop # Note for plugs: oder is important, as a plug may stop
# want to stop the pipeline! # want to stop the pipeline!
plug Plug.Logger, log: :debug plug(Plug.Logger, log: :debug)
# We use replug to allow for runtime configuration in release (as macros such # We use replug to allow for runtime configuration in release (as macros such
# as the `plug` call ae evaluated are compile-time). # as the `plug` call ae evaluated are compile-time).
plug Replug, plug(Replug,
plug: Plug.Static, plug: Plug.Static,
opts: {HAHandler, :acme_challenges_static_config} opts: {HAHandler, :acme_challenges_static_config}
plug Replug, )
plug(Replug,
plug: Plug.Static, plug: Plug.Static,
opts: {HAHandler, :assets_static_config} opts: {HAHandler, :assets_static_config}
)
plug :match plug(:match)
plug :dispatch plug(:dispatch)
get "/", do: Controller.index(conn) get("/", do: Controller.index(conn))
match _ do match _ do
send_resp(conn, 404, "Not found") send_resp(conn, 404, "Not found")