defmodule LivebookWeb.Hub.Teams.DeploymentGroupLive do use LivebookWeb, :live_view alias LivebookWeb.LayoutHelpers alias Livebook.Hubs alias Livebook.Teams alias Livebook.Hubs.Provider alias LivebookWeb.NotFoundError on_mount LivebookWeb.SidebarHook @impl true def handle_params(%{"id" => id} = params, _url, socket) do hub = Hubs.fetch_hub!(id) deployment_group_id = params["deployment_group_id"] secret_name = params["secret_name"] deployment_groups = Teams.get_deployment_groups(hub) default? = default_hub?(hub) deployment_group = if socket.assigns.live_action != :new_deployment_group do Enum.find_value(deployment_groups, &(&1.id == deployment_group_id && &1)) || raise( NotFoundError, "could not find deployment group matching #{inspect(deployment_group_id)}" ) end secrets = if socket.assigns.live_action != :new_deployment_group, do: deployment_group.secrets, else: [] secret_value = if socket.assigns.live_action == :edit_secret do Enum.find_value(secrets, &(&1.name == secret_name and &1.value)) || raise(NotFoundError, "could not find secret matching #{inspect(secret_name)}") end {:noreply, socket |> assign( hub: hub, deployment_groups: deployment_groups, deployment_group_id: deployment_group_id, deployment_group: deployment_group, hub_metadata: Provider.to_metadata(hub), secret_name: secret_name, secret_value: secret_value, default?: default?, secrets: secrets ) |> assign_new(:config_changeset, fn -> Hubs.Dockerfile.config_changeset() end) |> update_dockerfile()} end @impl true def render(assigns) do ~H"""
<%= Provider.connection_error(@hub) %>
<%= @hub.hub_emoji %>
<%= @hub.hub_name %> Livebook Teams <%= if @default? do %> Default <% end %>

<.link patch={~p"/hub/#{@hub.id}"} class="hover:text-blue-600 cursor-pointer"> <.remix_icon icon="arrow-left-line" /> Back to Hub

<.live_component module={LivebookWeb.Hub.Teams.DeploymentGroupFormComponent} id="deployment-groups" hub={@hub} deployment_group_id={@deployment_group_id} deployment_group={@deployment_group} return_to={~p"/hub/#{@hub.id}"} />
<%= if @deployment_group_id do %>

Secrets

Deployment group secrets overrides Hub secrets

<.live_component module={LivebookWeb.Hub.SecretListComponent} id="deployment-group-secrets-list" hub={@hub} secrets={@secrets} deployment_group={@deployment_group} add_path={ ~p"/hub/#{@hub.id}/deployment-groups/edit/#{@deployment_group.id}/secrets/new" } edit_path={"hub/#{@hub.id}/deployment-groups/edit/#{@deployment_group.id}/secrets/edit"} return_to={~p"/hub/#{@hub.id}/deployment-groups/edit/#{@deployment_group.id}"} />

Airgapped deployment

It is possible to deploy notebooks that belong to this Hub in an airgapped deployment, without connecting back to Livebook Teams server. Configure the deployment below and use the generated Dockerfile in a directory with notebooks that belong to your Organization.

<.form :let={f} for={@config_changeset} as={:data} phx-change="validate_dockerfile">
<% end %>
<.modal :if={@live_action in [:new_secret, :edit_secret]} id="secrets-modal" show width={:medium} patch={~p"/hub/#{@hub.id}/deployment-groups/edit/#{@deployment_group.id}"} > <.live_component module={LivebookWeb.Hub.SecretFormComponent} id="secrets" hub={@hub} deployment_group_id={@deployment_group.id} secret_name={@secret_name} secret_value={@secret_value} return_to={~p"/hub/#{@hub.id}/deployment-groups/edit/#{@deployment_group.id}"} /> """ end @impl true def handle_event("validate_dockerfile", %{"data" => data}, socket) do changeset = data |> Hubs.Dockerfile.config_changeset() |> Map.replace!(:action, :validate) {:noreply, socket |> assign(config_changeset: changeset) |> update_dockerfile()} end defp default_hub?(hub) do Hubs.get_default_hub().id == hub.id end defp update_dockerfile(socket) do config = socket.assigns.config_changeset |> Ecto.Changeset.apply_changes() |> Map.replace!(:deploy_all, true) %{hub: hub, secrets: deployment_group_secrets} = socket.assigns hub_secrets = Hubs.get_secrets(hub) hub_file_systems = Hubs.get_file_systems(hub, hub_only: true) secrets = Enum.uniq_by(deployment_group_secrets ++ hub_secrets, & &1.name) dockerfile = Hubs.Dockerfile.build_dockerfile(config, hub, secrets, hub_file_systems, nil, [], %{}) assign(socket, :dockerfile, dockerfile) end end