Add ability to remove NTS clients
This commit is contained in:
parent
3d03e4eb62
commit
feff0b29cd
|
@ -14,9 +14,43 @@ defmodule Chronoscope.NTS do
|
||||||
end
|
end
|
||||||
|
|
||||||
def list() do
|
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
|
NTS.DynamicSupervisor
|
||||||
|> DynamicSupervisor.which_children()
|
|> 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
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule Chronoscope.NTS.Client do
|
defmodule Chronoscope.NTS.Client do
|
||||||
use GenServer
|
use GenServer, restart: :transient
|
||||||
|
|
||||||
alias Chronoscope.NTS
|
alias Chronoscope.NTS
|
||||||
alias Chronoscope.NTS.KeyEstablishmentClient
|
alias Chronoscope.NTS.KeyEstablishmentClient
|
||||||
|
@ -23,6 +23,11 @@ defmodule Chronoscope.NTS.Client do
|
||||||
}}
|
}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_call(:terminate, _from, state) do
|
||||||
|
{:stop, :normal, self(), state}
|
||||||
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def handle_call(:list, _from, state) do
|
def handle_call(:list, _from, state) do
|
||||||
{:reply, state, state}
|
{:reply, state, state}
|
||||||
|
|
|
@ -10,18 +10,6 @@ defmodule Chronoscope.NTS.ClientTest do
|
||||||
|
|
||||||
setup :verify_on_exit!
|
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
|
setup _tags do
|
||||||
DateTimeMock
|
DateTimeMock
|
||||||
|> stub(:utc_now, fn -> ~U[2024-03-31 01:23:45Z] end)
|
|> stub(:utc_now, fn -> ~U[2024-03-31 01:23:45Z] end)
|
||||||
|
|
|
@ -12,18 +12,6 @@ defmodule Chronoscope.NTS.KeyEstablishmentClientTest do
|
||||||
|
|
||||||
@timeout 3000
|
@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
|
describe "Chronoscope.NTS.KeyEstablishmentClient.key_establishment()" do
|
||||||
test "sends the correct TLS options" do
|
test "sends the correct TLS options" do
|
||||||
SSLMock
|
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
|
defmodule Chronoscope.Case do
|
||||||
use ExUnit.CaseTemplate
|
use ExUnit.CaseTemplate
|
||||||
|
|
||||||
|
using do
|
||||||
|
quote do
|
||||||
|
import Chronoscope.Case
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
setup _tags do
|
setup _tags do
|
||||||
Mox.stub_with(Chronoscope.NTS.DateTimeMock, Chronoscope.DateTime.Stub)
|
Mox.stub_with(Chronoscope.NTS.DateTimeMock, Chronoscope.DateTime.Stub)
|
||||||
:ok
|
:ok
|
||||||
end
|
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
|
end
|
||||||
|
|
Loading…
Reference in New Issue