Add Offline Deployment section on the Hub Teams page (#2086)

This commit is contained in:
Alexandre de Souza 2023-07-19 16:57:54 -03:00 committed by GitHub
parent 5a79137390
commit 07caffaecb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 143 additions and 86 deletions

View file

@ -94,6 +94,7 @@ import "monaco-editor/esm/vs/basic-languages/sql/sql.contribution";
import "monaco-editor/esm/vs/basic-languages/css/css.contribution";
import "monaco-editor/esm/vs/basic-languages/html/html.contribution";
import "monaco-editor/esm/vs/basic-languages/xml/xml.contribution";
import "monaco-editor/esm/vs/basic-languages/dockerfile/dockerfile.contribution";
// === Configuration ===

View file

@ -25,7 +25,7 @@ config :mime, :types, %{
config :plug_cowboy, :log_exceptions_with_status_code, [407..599]
config :livebook,
teams_url: nil,
teams_url: "http://localhost:4100",
app_service_name: nil,
app_service_url: nil,
authentication_mode: :token,

View file

@ -207,10 +207,15 @@ defmodule Livebook.Application do
def create_offline_hub() do
name = System.get_env("LIVEBOOK_TEAMS_NAME")
teams_key = System.get_env("LIVEBOOK_TEAMS_KEY")
public_key = System.get_env("LIVEBOOK_TEAMS_OFFLINE_KEY")
if name && teams_key && public_key do
if name && public_key do
teams_key =
System.get_env("LIVEBOOK_TEAMS_KEY") ||
Livebook.Config.abort!(
"You specified LIVEBOOK_TEAMS_NAME, but LIVEBOOK_TEAMS_KEY is missing."
)
Livebook.Hubs.set_offline_hub(%Livebook.Hubs.Team{
id: "team-#{name}",
hub_name: name,

View file

@ -0,0 +1,4 @@
defmodule LivebookWeb.NotFoundError do
@moduledoc false
defexception [:message, plug_status: 404]
end

View file

@ -4,11 +4,7 @@ defmodule LivebookWeb.Hub.Edit.PersonalComponent do
alias Livebook.Hubs
alias Livebook.Hubs.Personal
alias LivebookWeb.LayoutHelpers
defmodule NotFoundError do
@moduledoc false
defexception [:message, plug_status: 404]
end
alias LivebookWeb.NotFoundError
@impl true
def update(assigns, socket) do

View file

@ -4,6 +4,7 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
alias Livebook.Hubs.Team
alias Livebook.Teams
alias LivebookWeb.LayoutHelpers
alias LivebookWeb.NotFoundError
@impl true
def update(assigns, socket) do
@ -15,7 +16,8 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
secret_value =
if assigns.live_action == :edit_secret do
Enum.find_value(secrets, &(&1.name == secret_name && &1.value))
Enum.find_value(secrets, &(&1.name == secret_name and &1.value)) ||
raise(NotFoundError, "could not find secret matching #{inspect(secret_name)}")
end
{:ok,
@ -26,6 +28,7 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
secret_name: secret_name,
secret_value: secret_value
)
|> assign_dockerfile()
|> assign_form(changeset)}
end
@ -101,86 +104,29 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
target={@myself}
/>
</div>
<div class="flex flex-col space-y-4">
<h2 class="text-xl text-gray-800 font-medium pb-2 border-b border-gray-200">
Offline Deployment
</h2>
<p class="text-gray-700">
Deploy your stamped notebooks with your Hub
using an instance of the Hub using
environment variables.
</p>
<.code_preview
source_id={"offline-deployment-#{@hub.id}"}
source={@dockerfile}
language="dockerfile"
/>
</div>
</div>
</div>
<.modal show={@show_key} id="show-key-modal" width={:medium} patch={~p"/hub/#{@hub.id}"}>
<div class="p-6 flex flex-col space-y-5">
<h3 class="text-2xl font-semibold text-gray-800">
Teams Key
</h3>
<div class="justify-center">
This is your <strong>Teams Key</strong>. If you want to join or invite others
to your organization, you will need to share your Teams Key with them. We
recommend storing it somewhere safe:
</div>
<div class=" w-full">
<div id="teams-key-toggle" class="relative flex">
<input
type="password"
id="teams-key"
readonly
value={@hub.teams_key}
class="input font-mono w-full border-neutral-200 bg-neutral-100 py-2 border-2 pr-8"
/>
<div class="flex items-center absolute inset-y-0 right-1">
<button
class="icon-button"
data-copy
data-tooltip="Copied to clipboard"
type="button"
aria-label="copy to clipboard"
phx-click={
JS.dispatch("lb:clipcopy", to: "#teams-key")
|> JS.add_class(
"tooltip top",
to: "#teams-key-toggle [data-copy]",
transition: {"ease-out duration-200", "opacity-0", "opacity-100"}
)
|> JS.remove_class(
"tooltip top",
to: "#teams-key-toggle [data-copy]",
transition: {"ease-out duration-200", "opacity-0", "opacity-100"},
time: 2000
)
}
>
<.remix_icon icon="clipboard-line" class="text-xl" />
</button>
<button
class="icon-button"
data-show
type="button"
aria-label="show password"
phx-click={
JS.remove_attribute("type", to: "#teams-key-toggle input")
|> JS.set_attribute({"type", "text"}, to: "#teams-key-toggle input")
|> toggle_class("hidden", to: "#teams-key-toggle [data-show]")
|> toggle_class("hidden", to: "#teams-key-toggle [data-hide]")
}
>
<.remix_icon icon="eye-line" class="text-xl" />
</button>
<button
class="icon-button hidden"
data-hide
type="button"
aria-label="hide password"
phx-click={
JS.remove_attribute("type", to: "#teams-key-toggle input")
|> JS.set_attribute({"type", "password"}, to: "#teams-key-toggle input")
|> toggle_class("hidden", to: "#teams-key-toggle [data-show]")
|> toggle_class("hidden", to: "#teams-key-toggle [data-hide]")
}
>
<.remix_icon icon="eye-off-line" class="text-xl" />
</button>
</div>
</div>
</div>
</div>
<.teams_key_modal teams_key={@hub.teams_key} />
</.modal>
<.modal
@ -203,6 +149,87 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
"""
end
defp teams_key_modal(assigns) do
~H"""
<div class="p-6 flex flex-col space-y-5">
<h3 class="text-2xl font-semibold text-gray-800">
Teams Key
</h3>
<div class="justify-center">
This is your <strong>Teams Key</strong>. If you want to join or invite others
to your organization, you will need to share your Teams Key with them. We
recommend storing it somewhere safe:
</div>
<div class=" w-full">
<div id="teams-key-toggle" class="relative flex">
<input
type="password"
id="teams-key"
readonly
value={@teams_key}
class="input font-mono w-full border-neutral-200 bg-neutral-100 py-2 border-2 pr-8"
/>
<div class="flex items-center absolute inset-y-0 right-1">
<button
class="icon-button"
data-copy
data-tooltip="Copied to clipboard"
type="button"
aria-label="copy to clipboard"
phx-click={
JS.dispatch("lb:clipcopy", to: "#teams-key")
|> JS.add_class(
"tooltip top",
to: "#teams-key-toggle [data-copy]",
transition: {"ease-out duration-200", "opacity-0", "opacity-100"}
)
|> JS.remove_class(
"tooltip top",
to: "#teams-key-toggle [data-copy]",
transition: {"ease-out duration-200", "opacity-0", "opacity-100"},
time: 2000
)
}
>
<.remix_icon icon="clipboard-line" class="text-xl" />
</button>
<button
class="icon-button"
data-show
type="button"
aria-label="show password"
phx-click={
JS.remove_attribute("type", to: "#teams-key-toggle input")
|> JS.set_attribute({"type", "text"}, to: "#teams-key-toggle input")
|> toggle_class("hidden", to: "#teams-key-toggle [data-show]")
|> toggle_class("hidden", to: "#teams-key-toggle [data-hide]")
}
>
<.remix_icon icon="eye-line" class="text-xl" />
</button>
<button
class="icon-button hidden"
data-hide
type="button"
aria-label="hide password"
phx-click={
JS.remove_attribute("type", to: "#teams-key-toggle input")
|> JS.set_attribute({"type", "password"}, to: "#teams-key-toggle input")
|> toggle_class("hidden", to: "#teams-key-toggle [data-show]")
|> toggle_class("hidden", to: "#teams-key-toggle [data-hide]")
}
>
<.remix_icon icon="eye-off-line" class="text-xl" />
</button>
</div>
</div>
</div>
</div>
"""
end
@impl true
def handle_event("save", %{"team" => params}, socket) do
case Teams.update_hub(socket.assigns.hub, params) do
@ -255,4 +282,22 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
defp assign_form(socket, %Ecto.Changeset{} = changeset) do
assign(socket, form: to_form(changeset))
end
defp assign_dockerfile(socket) do
version = to_string(Application.spec(:livebook, :vsn))
version = if version =~ "dev", do: "edge", else: version
assign(socket, :dockerfile, """
FROM livebook/livebook:#{version}
COPY /path/to/my/notebooks /data
ENV LIVEBOOK_APPS_PATH "/data"
ENV LIVEBOOK_APPS_PATH_HUB_ID "#{socket.assigns.hub.id}"
ENV LIVEBOOK_TEAMS_NAME "#{socket.assigns.hub.hub_name}"
ENV LIVEBOOK_TEAMS_OFFLINE_KEY "#{socket.assigns.hub.org_public_key}"
CMD [ "/app/bin/livebook", "start" ]\
""")
end
end

View file

@ -175,5 +175,11 @@ defmodule LivebookWeb.Integration.Hub.EditLiveTest do
refute render(element(view, "#hub-secrets-list")) =~ secret.name
refute secret in Livebook.Hubs.get_secrets(hub)
end
test "raises an error if does not exist secret", %{conn: conn, hub: hub} do
assert_raise LivebookWeb.NotFoundError, fn ->
live(conn, ~p"/hub/#{hub.id}/secrets/edit/HELLO")
end
end
end
end

View file

@ -42,7 +42,7 @@ defmodule LivebookWeb.Hub.EditLiveTest do
end
test "raises an error if does not exist secret", %{conn: conn, hub: hub} do
assert_raise LivebookWeb.Hub.Edit.PersonalComponent.NotFoundError, fn ->
assert_raise LivebookWeb.NotFoundError, fn ->
live(conn, ~p"/hub/#{hub.id}/secrets/edit/HELLO")
end
end