Refactor list_services() for clarity

This commit is contained in:
Harshad Sharma 2024-05-18 08:14:48 +05:30
parent e180aa8248
commit b452dc87d3
2 changed files with 119 additions and 68 deletions

View file

@ -4,70 +4,72 @@ defmodule Freedive.Api.Service.Cli do
""" """
require Logger require Logger
import Freedive.Api.Command import Freedive.Api.Command
import Freedive.Api.Service.Icons
@service_bin "/usr/sbin/service" @service_bin "/usr/sbin/service"
@skip_service_names ["DAEMON", "FILESYSTEMS", "LOGIN", "NETWORKING", "SERVERS"]
def list_services() do def list_services!() do
all_service_names = all_service_names()
enabled_service_names = enabled_service_names()
all_service_names
|> Enum.map(fn name -> service_details(name, Enum.member?(enabled_service_names, name)) end)
|> Enum.into(%{}, &{&1[:name], &1})
end
def all_service_names() do
case execute(@service_bin, ["-l"]) do case execute(@service_bin, ["-l"]) do
{:ok, stdout} -> {:ok, stdout} ->
service_names = stdout
stdout |> String.split("\n")
|> String.split("\n") |> Enum.map(&String.trim/1)
|> Enum.map(&String.trim/1) |> Enum.reject(&Enum.member?(@skip_service_names, &1))
|> Enum.reject(
&Enum.member?(["DAEMON", "FILESYSTEMS", "LOGIN", "NETWORKING", "SERVERS"], &1)
)
case execute(@service_bin, ["-e"]) do {:error, reason} ->
{:ok, stdout} -> Logger.error("List services: #{reason}")
enabled_service_names = raise "Failed to list services."
stdout
|> String.split("\n")
|> Enum.map(&String.trim/1)
|> Enum.map(&Path.basename/1)
|> Enum.into(%{}, &{&1, true})
services =
service_names
|> Enum.map(fn name ->
%{
name: name,
icon: "puzzle",
enabled: Map.has_key?(enabled_service_names, name),
running:
if Map.has_key?(enabled_service_names, name) do
service_is_running?(name)
else
nil
end,
description:
if Map.has_key?(enabled_service_names, name) do
case service_description(name) do
{:ok, desc} -> desc
_ -> nil
end
else
nil
end,
commands: nil,
rcvars: nil
}
end)
|> Enum.into(%{}, &{&1[:name], &1})
{:ok, services}
{:error, {stderr, _code}} ->
Logger.error("list_services enabled, log: #{inspect(stderr)}")
{:error, stderr}
end
{:error, {stderr, _code}} ->
Logger.error("list_services, log: #{inspect(stderr)}")
{:error, stderr}
end end
end end
def enabled_service_names() do
case execute(@service_bin, ["-e"]) do
{:ok, stdout} ->
stdout
|> String.split("\n")
|> Enum.map(&String.trim/1)
|> Enum.map(&Path.basename/1)
{:error, reason} ->
Logger.error("List enabled services: #{reason}")
raise "Failed to list enabled services."
end
end
def service_details(name, enabled \\ nil) do
enabled = if(enabled != nil, do: enabled, else: service_is_enabled?(name))
%{
name: name,
icon: icon_for_service(name),
enabled: enabled,
running: if(enabled, do: service_is_running?(name), else: nil),
description: if(enabled, do: service_description!(name), else: nil),
commands: if(enabled, do: service_commands!(name), else: nil),
log: []
}
end
def refresh(service) do
name = service.name
%{
service
| running: service_is_running?(name),
enabled: service_is_enabled?(name)
}
end
def service_is_running?(name, args \\ []) do def service_is_running?(name, args \\ []) do
case service(name, "onestatus", args) do case service(name, "onestatus", args) do
{:ok, _stdout} -> {:ok, _stdout} ->
@ -88,14 +90,33 @@ defmodule Freedive.Api.Service.Cli do
end end
end end
def service_description(name, args \\ []) do def service_status!(name, args \\ []) do
case service(name, "onestatus", args) do
{:ok, stdout} ->
stdout |> String.trim()
error ->
error
end
end
def service_description!(name, args \\ []) do
case service(name, "onedescribe", args) do case service(name, "onedescribe", args) do
{:ok, stdout} -> {:ok, stdout} ->
stdout = String.trim(stdout) stdout |> String.trim()
{:ok, stdout}
{:error, {stderr, _code}} -> error ->
{:error, stderr} error
end
end
def service_commands!(name, args \\ []) do
case service(name, "oneextracommands", args) do
{:ok, stdout} ->
stdout |> String.split(" ") |> Enum.map(&String.trim/1) |> Enum.reject(&(&1 == ""))
error ->
error
end end
end end
@ -106,6 +127,7 @@ defmodule Freedive.Api.Service.Cli do
{:ok, stdout} {:ok, stdout}
{:error, {stderr, code}} -> {:error, {stderr, code}} ->
# Logger.warning("service #{name} #{action}: #{String.trim(stderr)}")
{:error, {stderr, code}} {:error, {stderr, code}}
end end
end end

View file

@ -5,16 +5,42 @@ defmodule Freedive.Api.Service do
use GenServer use GenServer
require Logger require Logger
import Freedive.Api.Service.Cli import Freedive.Api.Service.Cli
import Freedive.Api.Service.Icons
@topic "system:service"
@events [:started, :stopped, :restarted]
def start_link(opts) do def start_link(opts) do
GenServer.start_link(__MODULE__, opts, name: __MODULE__) GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end end
def topic do
@topic
end
def events do
@events
end
def subscribe do
Phoenix.PubSub.subscribe(Freedive.PubSub, @topic)
end
def list() do def list() do
GenServer.call(__MODULE__, {:list}) GenServer.call(__MODULE__, {:list})
end end
def start(name) do
GenServer.cast(__MODULE__, {:start, name})
end
def stop(name) do
GenServer.cast(__MODULE__, {:stop, name})
end
def restart(name) do
GenServer.cast(__MODULE__, {:restart, name})
end
@impl true @impl true
def init(opts) do def init(opts) do
state = %{opts: opts, services: []} state = %{opts: opts, services: []}
@ -24,13 +50,7 @@ defmodule Freedive.Api.Service do
@impl true @impl true
def handle_continue(_opts, state) do def handle_continue(_opts, state) do
{:ok, services} = list_services() state = %{state | services: list_services!()}
services = services
|> Enum.map(fn {name, service} ->
{name, Map.put(service, :icon, icon_for_service(name))}
end)
|> Enum.into(%{})
state = %{state | services: services}
{:noreply, state} {:noreply, state}
end end
@ -39,4 +59,13 @@ defmodule Freedive.Api.Service do
services = state[:services] services = state[:services]
{:reply, services, state} {:reply, services, state}
end end
def broadcast(event, service) do
if event in @events do
service = refresh(service)
Phoenix.PubSub.broadcast(Freedive.PubSub, @topic, {event, service})
else
Logger.error("Service.Server broadcast: unknown event: #{event}")
end
end
end end