Add ability to remove NTS clients
This commit is contained in:
parent
3d03e4eb62
commit
feff0b29cd
|
@ -14,9 +14,43 @@ defmodule Chronoscope.NTS do
|
|||
end
|
||||
|
||||
def list() do
|
||||
call_all_clients(:list)
|
||||
end
|
||||
|
||||
def clear() do
|
||||
:terminate
|
||||
|> call_all_clients()
|
||||
|> Enum.map(&wait_for_termination/1)
|
||||
end
|
||||
|
||||
defp wait_for_termination(pid) do
|
||||
ref = Process.monitor(pid)
|
||||
|
||||
receive do
|
||||
{:DOWN, ^ref, _, _, _} -> {:ok, pid}
|
||||
after
|
||||
1000 -> {:error, pid}
|
||||
end
|
||||
end
|
||||
|
||||
defp call_all_clients(message) do
|
||||
NTS.DynamicSupervisor
|
||||
|> DynamicSupervisor.which_children()
|
||||
|> Enum.map(fn {_, pid, _, _} -> GenServer.call(pid, :list) end)
|
||||
|> Enum.map(fn {_, pid, _, _} -> GenServer.call(pid, message) end)
|
||||
end
|
||||
|
||||
def remove(host, port) do
|
||||
name = "#{host}:#{port}"
|
||||
|
||||
case Registry.lookup(NTS.Registry, name) do
|
||||
[{pid, _}] ->
|
||||
pid
|
||||
|> GenServer.call(:terminate)
|
||||
|> wait_for_termination()
|
||||
|
||||
[] ->
|
||||
{:error, :notfound}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Chronoscope.NTS.Client do
|
||||
use GenServer
|
||||
use GenServer, restart: :transient
|
||||
|
||||
alias Chronoscope.NTS
|
||||
alias Chronoscope.NTS.KeyEstablishmentClient
|
||||
|
@ -23,6 +23,11 @@ defmodule Chronoscope.NTS.Client do
|
|||
}}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_call(:terminate, _from, state) do
|
||||
{:stop, :normal, self(), state}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_call(:list, _from, state) do
|
||||
{:reply, state, state}
|
||||
|
|
|
@ -10,18 +10,6 @@ defmodule Chronoscope.NTS.ClientTest do
|
|||
|
||||
setup :verify_on_exit!
|
||||
|
||||
defp peercert() do
|
||||
:secp256r1
|
||||
|> X509.PrivateKey.new_ec()
|
||||
|> X509.Certificate.self_signed("/C=US/ST=CA/L=San Francisco/O=Acme/CN=Test")
|
||||
|> X509.Certificate.to_der()
|
||||
end
|
||||
|
||||
defp send_ssl_response(response) do
|
||||
send(self(), {:ssl, nil, response})
|
||||
:ok
|
||||
end
|
||||
|
||||
setup _tags do
|
||||
DateTimeMock
|
||||
|> stub(:utc_now, fn -> ~U[2024-03-31 01:23:45Z] end)
|
||||
|
|
|
@ -12,18 +12,6 @@ defmodule Chronoscope.NTS.KeyEstablishmentClientTest do
|
|||
|
||||
@timeout 3000
|
||||
|
||||
defp peercert() do
|
||||
:secp256r1
|
||||
|> X509.PrivateKey.new_ec()
|
||||
|> X509.Certificate.self_signed("/C=US/ST=CA/L=San Francisco/O=Acme/CN=Test")
|
||||
|> X509.Certificate.to_der()
|
||||
end
|
||||
|
||||
defp send_ssl_response(response) do
|
||||
send(self(), {:ssl, nil, response})
|
||||
:ok
|
||||
end
|
||||
|
||||
describe "Chronoscope.NTS.KeyEstablishmentClient.key_establishment()" do
|
||||
test "sends the correct TLS options" do
|
||||
SSLMock
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
defmodule Chronoscope.NTSTest do
|
||||
use Chronoscope.Case
|
||||
|
||||
alias Chronoscope.NTS.SSLMock
|
||||
|
||||
import Chronoscope.NTS
|
||||
import Mox
|
||||
|
||||
setup :verify_on_exit!
|
||||
setup :set_mox_global
|
||||
|
||||
defp expect_key_establishment(host, port) do
|
||||
host_charlist = to_charlist(host)
|
||||
|
||||
SSLMock
|
||||
|> expect(:connect, fn ^host_charlist, ^port, _, _ -> {:ok, :socket} end)
|
||||
|> expect(:send, fn :socket, _ -> send_ssl_response([]) end)
|
||||
|> expect(:peercert, fn :socket -> {:ok, peercert()} end)
|
||||
|> expect(:close, fn :socket -> :ok end)
|
||||
end
|
||||
|
||||
setup do
|
||||
clear()
|
||||
on_exit(fn -> clear() end)
|
||||
end
|
||||
|
||||
describe "Chronoscope.NTS.healthy?()" do
|
||||
test "is healthy" do
|
||||
assert healthy?() == true
|
||||
end
|
||||
end
|
||||
|
||||
describe "Chronoscope.NTS.list()" do
|
||||
test "shows empty client list" do
|
||||
assert list() == []
|
||||
end
|
||||
|
||||
test "shows all clients" do
|
||||
expect_key_establishment("localhost", 4444)
|
||||
key_establishment("localhost", 4444)
|
||||
|
||||
assert [%{host: "localhost", key_establishment_response: _, last_key_establishment: _, port: 4444}] = list()
|
||||
end
|
||||
end
|
||||
|
||||
describe "Chronoscope.NTS.remove()" do
|
||||
test "removes a client" do
|
||||
expect_key_establishment("localhost", 4444)
|
||||
key_establishment("localhost", 4444)
|
||||
|
||||
assert {:ok, _} = remove("localhost", 4444)
|
||||
assert list() == []
|
||||
end
|
||||
|
||||
test "does nothing if the client doesn't exist" do
|
||||
expect_key_establishment("localhost", 4444)
|
||||
key_establishment("localhost", 4444)
|
||||
|
||||
assert remove("localhost", 1111) == {:error, :notfound}
|
||||
assert [%{host: "localhost", key_establishment_response: _, last_key_establishment: _, port: 4444}] = list()
|
||||
end
|
||||
end
|
||||
|
||||
describe "Chronoscope.NTS.key_establishment()" do
|
||||
test "creates and reuses a client" do
|
||||
expect_key_establishment("localhost", 4444)
|
||||
|
||||
assert {:ok, %{cert_expiration: _}} = key_establishment("localhost", 4444)
|
||||
assert {:ok, %{cert_expiration: _}} = key_establishment("localhost", 4444)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,8 +1,26 @@
|
|||
defmodule Chronoscope.Case do
|
||||
use ExUnit.CaseTemplate
|
||||
|
||||
using do
|
||||
quote do
|
||||
import Chronoscope.Case
|
||||
end
|
||||
end
|
||||
|
||||
setup _tags do
|
||||
Mox.stub_with(Chronoscope.NTS.DateTimeMock, Chronoscope.DateTime.Stub)
|
||||
:ok
|
||||
end
|
||||
|
||||
def peercert() do
|
||||
:secp256r1
|
||||
|> X509.PrivateKey.new_ec()
|
||||
|> X509.Certificate.self_signed("/C=US/ST=CA/L=San Francisco/O=Acme/CN=Test")
|
||||
|> X509.Certificate.to_der()
|
||||
end
|
||||
|
||||
def send_ssl_response(response) do
|
||||
send(self(), {:ssl, nil, response})
|
||||
:ok
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue