diff --git a/apps/foundation/lib/foundation/application.ex b/apps/foundation/lib/foundation/application.ex index ff5072e6..c60dc956 100644 --- a/apps/foundation/lib/foundation/application.ex +++ b/apps/foundation/lib/foundation/application.ex @@ -19,7 +19,6 @@ defmodule Foundation.Application do {Finch, name: Foundation.Finch}, Foundation.Catalog.Local, Foundation.Certificates.Manager.Supervisor, - Foundation.Certificate, Foundation.Notifications.Supervisor ] @@ -29,6 +28,7 @@ defmodule Foundation.Application do case Supervisor.start_link(children, opts) do {:ok, _pid} = response -> + Foundation.Certificate.initialize_certificate_manager() Foundation.Notifications.initialize_notification_manager() response diff --git a/apps/foundation/lib/foundation/certificate.ex b/apps/foundation/lib/foundation/certificate.ex index b0e56394..b448b792 100644 --- a/apps/foundation/lib/foundation/certificate.ex +++ b/apps/foundation/lib/foundation/certificate.ex @@ -1,37 +1,16 @@ defmodule Foundation.Certificate do @moduledoc """ - GenServer responsible for bootstrapping and coordinating certificate managers + Provides functions for bootstrapping and managing certificate managers across all registered applications. - """ - - use GenServer - import Foundation.Macros + On application startup, `initialize_certificate_manager/0` is called to + start a certificate manager for each application that declares certificates + in its catalog entry. Individual managers can also be started or stopped + on demand via `start_certificate_manager/2` and `stop_certificate_manager/1`. + """ alias Foundation.Certificates.Manager.Supervisor - require Logger - - ### ========================================================================== - ### Callback functions - ### ========================================================================== - - def start_link(args) do - GenServer.start_link(__MODULE__, args, name: __MODULE__) - end - - @impl true - def init(_args) do - Logger.info("Initializing Certificate Server") - {:ok, %{}, {:continue, :start_certificate_manager}} - end - - @impl true - def handle_continue(:start_certificate_manager, state) do - initialize_certificate_manager() - {:noreply, state} - end - ### ========================================================================== ### Public Functions ### ========================================================================== @@ -53,23 +32,20 @@ defmodule Foundation.Certificate do ### Private Functions ### ========================================================================== - if_not_test do - alias Foundation.Catalog - - defp initialize_certificate_manager do - Catalog.applications() - |> Enum.each(fn - %{certificates: []} -> - :ok - - %{name: app_name, certificates: certificates} -> - Enum.each( - certificates, - &Supervisor.start_certificate_manager(app_name, &1) - ) - end) - end - else - defp initialize_certificate_manager, do: :ok + @spec initialize_certificate_manager() :: :ok + def initialize_certificate_manager do + Foundation.Catalog.applications() + |> Enum.each(fn + %{certificates: []} -> + :ok + + %{name: app_name, certificates: certificates} -> + Enum.each( + certificates, + &Supervisor.start_certificate_manager(app_name, &1) + ) + end) + + :ok end end diff --git a/apps/foundation/lib/foundation/notifications.ex b/apps/foundation/lib/foundation/notifications.ex index fa7b5a28..3977ddac 100644 --- a/apps/foundation/lib/foundation/notifications.ex +++ b/apps/foundation/lib/foundation/notifications.ex @@ -85,11 +85,14 @@ defmodule Foundation.Notifications do ### ========================================================================== ### Public Functions ### ========================================================================== + @spec initialize_notification_manager() :: :ok def initialize_notification_manager do :foundation |> Application.fetch_env!(:notifications) |> Enum.map(&to_notification_struct/1) - |> Enum.map(&Foundation.Notifications.Supervisor.start_notification_worker/1) + |> Enum.each(&Foundation.Notifications.Supervisor.start_notification_worker/1) + + :ok end @doc """ diff --git a/apps/foundation/test/certificate_test.exs b/apps/foundation/test/certificate_test.exs index ed6a803a..3064e32e 100644 --- a/apps/foundation/test/certificate_test.exs +++ b/apps/foundation/test/certificate_test.exs @@ -1,59 +1,10 @@ defmodule Foundation.CertificateTest do use ExUnit.Case, async: false - import ExUnit.CaptureLog import Mock alias Foundation.Certificate alias Foundation.Certificates.Manager.Supervisor - - # --------------------------------------------------------------------------- - # init/1 - # --------------------------------------------------------------------------- - - describe "init/1" do - @tag :capture_log - test "logs initialization message" do - log = - capture_log(fn -> - {:ok, pid} = GenServer.start_link(Certificate, []) - # Give the continue a moment to fire before we stop. - Process.sleep(50) - GenServer.stop(pid) - end) - - assert log =~ "Initializing Certificate Server" - end - - @tag :capture_log - test "returns initial state as empty map" do - # We inspect via :sys.get_state; the continue callback runs first but - # does not modify the state, so it stays %{}. - {:ok, pid} = GenServer.start_link(Certificate, []) - Process.sleep(50) - assert :sys.get_state(pid) == %{} - GenServer.stop(pid) - end - end - - # --------------------------------------------------------------------------- - # handle_continue :start_certificate_manager (test env) - # --------------------------------------------------------------------------- - - describe "handle_continue :start_certificate_manager (test environment)" do - @tag :capture_log - test "does not call Supervisor.start_certificate_manager in test env" do - # In test mode Foundation.Certificate uses the no-op initialize_certificate_manager/0, - # so the supervisor must never be contacted. - with_mock Supervisor, start_certificate_manager: fn _name, _cert -> {:ok, self()} end do - {:ok, pid} = GenServer.start_link(Certificate, []) - Process.sleep(50) - refute called(Supervisor.start_certificate_manager(:_, :_)) - GenServer.stop(pid) - end - end - end - # --------------------------------------------------------------------------- # stop_certificate_manager/1 # --------------------------------------------------------------------------- diff --git a/config/test.exs b/config/test.exs index 5e32b90a..f1e8b37d 100644 --- a/config/test.exs +++ b/config/test.exs @@ -22,6 +22,7 @@ config :foundation, deploy_schedule_interval_ms: 5000, replica_ports: [%{key: "PORT", base: 4444}], env: ["SECRET=value", "PHX_SERVER=true"], + certificates: [], monitoring: [ port: %{ enable_restart: true, @@ -48,6 +49,7 @@ config :foundation, deploy_schedule_interval_ms: 5000, replica_ports: [%{key: "PORT", base: 5555}], env: ["SECRET=value", "PHX_SERVER=true"], + certificates: [], monitoring: [ port: %{ enable_restart: false, @@ -74,6 +76,7 @@ config :foundation, deploy_schedule_interval_ms: 5000, replica_ports: [%{key: "PORT", base: 6666}], env: ["SECRET=value", "PHX_SERVER=true"], + certificates: [], monitoring: [] } ]