feat(server): hosts list/delete/rotate helpers + pubsub on metric insert
This commit is contained in:
parent
f3e7fab4d2
commit
3123743c1c
4 changed files with 77 additions and 2 deletions
|
|
@ -63,4 +63,27 @@ defmodule Server.Hosts do
|
|||
defp generate_token do
|
||||
:crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false)
|
||||
end
|
||||
|
||||
@spec list_all() :: [Host.t()]
|
||||
def list_all do
|
||||
import Ecto.Query
|
||||
Repo.all(from h in Host, order_by: [asc: h.name])
|
||||
end
|
||||
|
||||
@spec delete_host(Host.t()) :: {:ok, Host.t()} | {:error, Ecto.Changeset.t()}
|
||||
def delete_host(%Host{} = host), do: Repo.delete(host)
|
||||
|
||||
@spec rotate_token(Host.t()) :: {:ok, {Host.t(), String.t()}} | {:error, Ecto.Changeset.t()}
|
||||
def rotate_token(%Host{} = host) do
|
||||
token = generate_token()
|
||||
hash = Bcrypt.hash_pwd_salt(token)
|
||||
|
||||
host
|
||||
|> Ecto.Changeset.change(token_hash: hash)
|
||||
|> Repo.update()
|
||||
|> case do
|
||||
{:ok, updated} -> {:ok, {updated, token}}
|
||||
{:error, cs} -> {:error, cs}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -18,11 +18,25 @@ defmodule Server.Metrics do
|
|||
})
|
||||
|
||||
with %Ecto.Changeset{valid?: true} = cs <- changeset,
|
||||
true <- host_exists?(host_id) || {:host_missing, cs} do
|
||||
Repo.insert(cs)
|
||||
true <- host_exists?(host_id) || {:host_missing, cs},
|
||||
{:ok, metric} <- Repo.insert(cs) do
|
||||
Phoenix.PubSub.broadcast(
|
||||
Server.PubSub,
|
||||
"metrics",
|
||||
{:metric_inserted, host_id, interval_type}
|
||||
)
|
||||
|
||||
Phoenix.PubSub.broadcast(
|
||||
Server.PubSub,
|
||||
"metrics:#{host_id}",
|
||||
{:metric_inserted, host_id, interval_type}
|
||||
)
|
||||
|
||||
{:ok, metric}
|
||||
else
|
||||
%Ecto.Changeset{} = cs -> {:error, cs}
|
||||
{:host_missing, cs} -> {:error, Ecto.Changeset.add_error(cs, :host, "does not exist")}
|
||||
{:error, %Ecto.Changeset{} = cs} -> {:error, cs}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -52,4 +52,34 @@ defmodule Server.HostsTest do
|
|||
assert offline.status == "offline"
|
||||
end
|
||||
end
|
||||
|
||||
describe "list_all/0" do
|
||||
test "returns every host ordered by name" do
|
||||
{:ok, {_, _}} = Hosts.create_host("pve-02")
|
||||
{:ok, {_, _}} = Hosts.create_host("pve-01")
|
||||
names = Hosts.list_all() |> Enum.map(& &1.name)
|
||||
assert names == ["pve-01", "pve-02"]
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete_host/1" do
|
||||
test "deletes the host row" do
|
||||
{:ok, {host, _}} = Hosts.create_host("pve-01")
|
||||
assert {:ok, _} = Hosts.delete_host(host)
|
||||
assert Server.Repo.get(Server.Schema.Host, host.id) == nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "rotate_token/1" do
|
||||
test "replaces token_hash and returns new plaintext token" do
|
||||
{:ok, {host, old_token}} = Hosts.create_host("pve-01")
|
||||
assert {:ok, {updated, new_token}} = Hosts.rotate_token(host)
|
||||
assert updated.id == host.id
|
||||
refute updated.token_hash == host.token_hash
|
||||
assert is_binary(new_token)
|
||||
refute new_token == old_token
|
||||
assert {:error, :invalid_token} = Hosts.authenticate("pve-01", old_token)
|
||||
assert {:ok, _} = Hosts.authenticate("pve-01", new_token)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -32,6 +32,14 @@ defmodule Server.MetricsTest do
|
|||
assert {:error, cs} = Metrics.record_sample(999_999, "fast", ts, %{})
|
||||
assert %{host: ["does not exist"]} = errors_on(cs)
|
||||
end
|
||||
|
||||
test "broadcasts {:metric_inserted, host_id, interval} on success", %{host: host} do
|
||||
Phoenix.PubSub.subscribe(Server.PubSub, "metrics")
|
||||
ts = DateTime.utc_now()
|
||||
{:ok, _} = Metrics.record_sample(host.id, "fast", ts, %{"v" => 1})
|
||||
assert_receive {:metric_inserted, host_id, "fast"}, 500
|
||||
assert host_id == host.id
|
||||
end
|
||||
end
|
||||
|
||||
describe "latest_sample/2" do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue