dotfiles/backend/lib/prymn/servers.ex
Nikos Papadakis 7fe45ca94b
setup CI and a more complete installation script
Use woodpecker-ci to deploy binaries to the R2 object storage. Use
multi-target builds to deploy multiple binaries for one or more CPU
architectures.

Now the installation script lives on the root of the repo, and it is
more complete checking the machine's requirements, operating system and
cpu architecture.
2023-07-19 23:01:18 +03:00

136 lines
2.8 KiB
Elixir

defmodule Prymn.Servers do
@moduledoc """
The Servers context.
"""
import Ecto.Query, warn: false
alias Prymn.Repo
alias Prymn.Servers.Server
@doc """
Returns the list of servers.
## Examples
iex> list_servers()
[%Server{}, ...]
"""
def list_servers do
Repo.all(Server)
end
@doc """
Gets a single server.
Raises `Ecto.NoResultsError` if the Server does not exist.
## Examples
iex> get_server!(123)
%Server{}
iex> get_server!(456)
** (Ecto.NoResultsError)
"""
def get_server!(id), do: Repo.get!(Server, id)
@doc """
Get a single server by its IP.
"""
@spec get_server_by_ip!(String.t()) :: %Server{}
def get_server_by_ip!(ip), do: Repo.get_by!(Server, public_ip: ip)
@doc """
Start a new server connection with the app.
"""
def create_server(attrs \\ %{}) do
# Create a unique registration token
%Server{registration_token: :crypto.strong_rand_bytes(16)}
|> Server.changeset(attrs)
|> Repo.insert()
end
@doc """
Registers a server using a registration token.
"""
def register_server(token, public_ip) do
with true <- :inet.is_ip_address(public_ip),
{:ok, token} <- Base.decode64(token) do
public_ip_string =
public_ip
|> :inet.ntoa()
|> to_string()
from(s in Server, where: s.registration_token == ^token, select: s)
|> Repo.one!()
|> update_server(%{public_ip: public_ip_string, status: :registered})
else
false -> {:error, :invalid_ip}
:error -> {:error, :bad_token}
end
end
@doc """
Updates a server.
## Examples
iex> update_server(server, %{field: new_value})
{:ok, %Server{}}
iex> update_server(server, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_server(%Server{} = server, attrs) do
server
|> Server.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes a server.
## Examples
iex> delete_server(server)
{:ok, %Server{}}
iex> delete_server(server)
{:error, %Ecto.Changeset{}}
"""
def delete_server(%Server{} = server) do
Repo.delete(server)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking server changes.
## Examples
iex> change_server(server)
%Ecto.Changeset{data: %Server{}}
"""
def change_server(%Server{} = server, attrs \\ %{}) do
Server.changeset(server, attrs)
end
@doc """
Returns a string containing the command that needs to be executed to the
remote server in order to register it to the backend.
"""
@spec create_setup_command(%Server{}) :: String.t()
def create_setup_command(%Server{registration_token: token}) do
token
|> Base.encode64()
|> then(fn token ->
"curl -sSfL " <> PrymnWeb.Endpoint.url() <> "/install | sh -s " <> token
end)
end
end