Packages
livebook
0.9.1
0.19.8
0.19.7
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.6
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.3
0.17.2
0.17.1
0.17.0
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.14.0-rc.1
0.14.0-rc.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.2
0.1.1
0.1.0
Automate code & data workflows with interactive notebooks
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/livebook/hubs/enterprise.ex
defmodule Livebook.Hubs.Enterprise do
@moduledoc false
use Ecto.Schema
import Ecto.Changeset
alias Livebook.Hubs
@type t :: %__MODULE__{
id: String.t() | nil,
url: String.t() | nil,
token: String.t() | nil,
external_id: String.t() | nil,
hub_name: String.t() | nil,
hub_emoji: String.t() | nil
}
embedded_schema do
field :url, :string
field :token, :string
field :external_id, :string
field :hub_name, :string
field :hub_emoji, :string
end
@fields ~w(
url
token
external_id
hub_name
hub_emoji
)a
@doc """
Returns an `%Ecto.Changeset{}` for tracking hub changes.
"""
@spec change_hub(t(), map()) :: Ecto.Changeset.t()
def change_hub(%__MODULE__{} = enterprise, attrs \\ %{}) do
changeset(enterprise, attrs)
end
@doc """
Returns changeset with applied validations.
"""
@spec validate_hub(t(), map()) :: Ecto.Changeset.t()
def validate_hub(%__MODULE__{} = enterprise, attrs \\ %{}) do
enterprise
|> changeset(attrs)
|> Map.put(:action, :validate)
end
@doc """
Creates a Hub.
With success, notifies interested processes about hub metadatas data change.
Otherwise, it will return an error tuple with changeset.
"""
@spec create_hub(t(), map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()}
def create_hub(%__MODULE__{} = enterprise, attrs) do
changeset = changeset(enterprise, attrs)
id = get_field(changeset, :id)
if Hubs.hub_exists?(id) do
{:error,
changeset
|> add_error(:external_id, "already exists")
|> Map.replace!(:action, :validate)}
else
with {:ok, struct} <- apply_action(changeset, :insert) do
Hubs.save_hub(struct)
{:ok, struct}
end
end
end
@doc """
Updates a Hub.
With success, notifies interested processes about hub metadatas data change.
Otherwise, it will return an error tuple with changeset.
"""
@spec update_hub(t(), map()) :: {:ok, t()} | {:error, Ecto.Changeset.t()}
def update_hub(%__MODULE__{} = enterprise, attrs) do
changeset = changeset(enterprise, attrs)
id = get_field(changeset, :id)
if Hubs.hub_exists?(id) do
with {:ok, struct} <- apply_action(changeset, :update) do
Hubs.save_hub(struct)
{:ok, struct}
end
else
{:error,
changeset
|> add_error(:external_id, "does not exists")
|> Map.replace!(:action, :validate)}
end
end
defp changeset(enterprise, attrs) do
enterprise
|> cast(attrs, @fields)
|> validate_required(@fields)
|> add_id()
end
defp add_id(changeset) do
case get_field(changeset, :external_id) do
nil -> changeset
external_id -> put_change(changeset, :id, "enterprise-#{external_id}")
end
end
end
defimpl Livebook.Hubs.Provider, for: Livebook.Hubs.Enterprise do
alias Livebook.Hubs.EnterpriseClient
def load(enterprise, fields) do
%{
enterprise
| id: fields.id,
url: fields.url,
token: fields.token,
external_id: fields.external_id,
hub_name: fields.hub_name,
hub_emoji: fields.hub_emoji
}
end
def to_metadata(enterprise) do
%Livebook.Hubs.Metadata{
id: enterprise.id,
name: enterprise.hub_name,
provider: enterprise,
emoji: enterprise.hub_emoji,
connected?: EnterpriseClient.connected?(enterprise.id)
}
end
def type(_enterprise), do: "enterprise"
def connection_spec(enterprise), do: {EnterpriseClient, enterprise}
def disconnect(enterprise) do
EnterpriseClient.stop(enterprise.id)
end
def capabilities(_enterprise), do: ~w(connect list_secrets create_secret)a
def get_secrets(enterprise) do
EnterpriseClient.get_secrets(enterprise.id)
end
def create_secret(enterprise, secret) do
data = LivebookProto.build_create_secret_request(name: secret.name, value: secret.value)
case EnterpriseClient.send_request(enterprise.id, data) do
{:create_secret, _} ->
:ok
{:changeset_error, errors} ->
changeset =
for {field, messages} <- errors,
message <- messages,
reduce: secret do
acc ->
Livebook.Secrets.add_secret_error(acc, field, message)
end
{:error, changeset}
{:transport_error, reason} ->
message = "#{enterprise.hub_emoji} #{enterprise.hub_name}: #{reason}"
changeset = Livebook.Secrets.add_secret_error(secret, :hub_id, message)
{:error, changeset}
end
end
def update_secret(_enterprise, _secret), do: raise("not implemented")
def delete_secret(_enterprise, _secret), do: raise("not implemented")
def connection_error(enterprise) do
reason = EnterpriseClient.get_connection_error(enterprise.id)
"Cannot connect to Hub: #{reason}. Will attempt to reconnect automatically..."
end
# TODO: implement signing through the enterprise server
def notebook_stamp(_hub, _notebook_source, _metadata) do
:skip
end
def verify_notebook_stamp(_hub, _notebook_source, _stamp), do: raise("not implemented")
end