Simplify code that is no longer shared across views

This commit is contained in:
José Valim 2024-04-08 11:06:08 +02:00
parent 4c6869d69c
commit cb11b26cdc
9 changed files with 135 additions and 153 deletions

View file

@ -309,7 +309,7 @@ defmodule Livebook.Teams.Requests do
{:ok, %{status: 401}} -> {:ok, %{status: 401}} ->
{:transport_error, {:transport_error,
"You are not authorized to perform this action, make sure you have the access or you are not in a Livebook Agent/Offline instance"} "You are not authorized to perform this action, make sure you have the access and you are not in a Livebook App Server/Offline instance"}
_otherwise -> _otherwise ->
{:transport_error, @error_message} {:transport_error, @error_message}

View file

@ -82,30 +82,6 @@ defmodule LivebookWeb.AppComponents do
) )
end end
@doc """
Renders form fields for Dockerfile configuration.
"""
attr :form, Phoenix.HTML.Form, required: true
attr :hub, :map, required: true
attr :show_deploy_all, :boolean, default: true
def docker_config_form_content(assigns) do
~H"""
<div class="flex flex-col space-y-4">
<.radio_field
:if={@show_deploy_all}
label="Deploy"
field={@form[:deploy_all]}
options={[
{"false", "Only this notebook"},
{"true", "All notebooks in the current directory"}
]}
/>
<.radio_field label="Base image" field={@form[:docker_tag]} options={docker_tag_options()} />
</div>
"""
end
@doc """ @doc """
Renders form fields for Deployment Group. Renders form fields for Deployment Group.
""" """
@ -184,103 +160,18 @@ defmodule LivebookWeb.AppComponents do
defp zta_options(), do: @zta_options defp zta_options(), do: @zta_options
@docker_tag_options for image <- Livebook.Config.docker_images(), do: {image.tag, image.name}
defp docker_tag_options(), do: @docker_tag_options
@doc """
Renders Docker deployment instruction for an app.
"""
attr :hub, :map, required: true
attr :dockerfile, :string, required: true
attr :dockerfile_config, :map, required: true
slot :dockerfile_actions, default: nil
def docker_instructions(assigns) do
~H"""
<div class="flex flex-col gap-4">
<div>
<div class="flex items-end mb-1 gap-1">
<span class="text-sm text-gray-700 font-semibold">Dockerfile</span>
<div class="grow" />
<%= render_slot(@dockerfile_actions) %>
<.button
color="gray"
small
data-tooltip="Copied to clipboard"
type="button"
aria-label="copy to clipboard"
phx-click={
JS.dispatch("lb:clipcopy", to: "#dockerfile-source")
|> JS.transition("tooltip top", time: 2000)
}
>
<.remix_icon icon="clipboard-line" />
<span>Copy source</span>
</.button>
</div>
<.code_preview source_id="dockerfile-source" source={@dockerfile} language="dockerfile" />
</div>
<div class="text-gray-700">
To test the deployment locally, go the the notebook directory, save the Dockerfile, then run:
</div>
<.code_preview
source_id="dockerfile-cmd"
source={
~s'''
docker build -t my-app .
docker run --rm -p 8080:8080 -p 8081:8081 my-app
'''
}
language="text"
/>
<p class="text-gray-700 py-2">
You may additionally perform the following optional steps:
</p>
<ul class="text-gray-700 space-y-3">
<li :if={Hubs.Provider.type(@hub) == "team"} class="flex gap-2">
<div><.remix_icon icon="arrow-right-line" class="text-gray-900" /></div>
<span>
you may remove the default value for <code>TEAMS_KEY</code>
from your Dockerfile and set it as a build argument in your deployment
platform
</span>
</li>
<li :if={@dockerfile_config.clustering} class="flex gap-2">
<div><.remix_icon icon="arrow-right-line" class="text-gray-900" /></div>
<span>
you may set <code>LIVEBOOK_SECRET_KEY_BASE</code>
and <code>LIVEBOOK_COOKIE</code>
as runtime environment secrets in your deployment platform, to ensure their
values stay the same across deployments. If you do that, you can remove
the defaults from your Dockerfile
</span>
</li>
<li class="flex gap-2">
<div><.remix_icon icon="arrow-right-line" class="text-gray-900" /></div>
<span>
if you want to debug your deployed notebooks in production, you may
set the <code>LIVEBOOK_PASSWORD</code> environment variable with a
value of at least 12 characters of your choice
</span>
</li>
</ul>
</div>
"""
end
defp zta_metadata(nil), do: nil defp zta_metadata(nil), do: nil
defp zta_metadata(zta_provider) do defp zta_metadata(zta_provider) do
Enum.find(Livebook.Config.identity_providers(), &(&1.type == zta_provider)) Enum.find(Livebook.Config.identity_providers(), &(&1.type == zta_provider))
end end
@doc """
Lists all docker tag options.
"""
@docker_tag_options for image <- Livebook.Config.docker_images(), do: {image.tag, image.name}
def docker_tag_options(), do: @docker_tag_options
@doc """ @doc """
Updates app list with the given apps event. Updates app list with the given apps event.
""" """

View file

@ -162,7 +162,8 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
</h2> </h2>
<p class="text-gray-700"> <p class="text-gray-700">
Secrets are a safe way to share credentials and tokens with notebooks. Secrets are a safe way to share credentials and tokens with notebooks
across your whole team.
They are often used by Smart cells and can be read as They are often used by Smart cells and can be read as
environment variables using the <code>LB_</code> prefix. environment variables using the <code>LB_</code> prefix.
</p> </p>
@ -189,7 +190,7 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
</h2> </h2>
<p class="text-gray-700"> <p class="text-gray-700">
File storages are used to store notebooks and their files. File storages are used to store notebooks and their files across your whole team.
</p> </p>
<.live_component <.live_component

View file

@ -33,11 +33,11 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupComponent do
<h3 class="font-semibold"><%= @deployment_group.name %></h3> <h3 class="font-semibold"><%= @deployment_group.name %></h3>
<%= if @deployment_group.mode == :online do %> <%= if @deployment_group.mode == :online do %>
<div class="bg-green-100 text-green-800 text-xs px-2.5 py-0.5 rounded cursor-default"> <div class="bg-green-100 text-green-800 text-xs px-2.5 py-0.5 rounded cursor-default">
<%= @deployment_group.mode %> Online
</div> </div>
<% else %> <% else %>
<div class="bg-red-100 text-red-800 text-xs px-2.5 py-0.5 rounded cursor-default"> <div class="bg-red-100 text-red-800 text-xs px-2.5 py-0.5 rounded cursor-default">
<%= @deployment_group.mode %> Airgapped
</div> </div>
<% end %> <% end %>
</div> </div>

View file

@ -123,9 +123,8 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
defp content(assigns) do defp content(assigns) do
~H""" ~H"""
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
<p class="text-gray-700"> <p class="text-gray-700 pb-4">
You can deploy this app in the cloud using Docker. To do that, configure Choose your deployment settings and then deploy your notebook using the generated Dockerfile.
the deployment and then use the generated Dockerfile.
</p> </p>
<div class="flex gap-12"> <div class="flex gap-12">
@ -158,7 +157,16 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
<.label help={deployment_group_help()}> <.label help={deployment_group_help()}>
Deployment Group Deployment Group
</.label> </.label>
<span>No deployment groups available</span> <span>
None configured
<.link
navigate={~p"/hub/#{@hub.id}/groups/new"}
target="_blank"
class="pl-3 text-blue-600 font-semibold"
>
+ add new
</.link>
</span>
</p> </p>
<% end %> <% end %>
<% end %> <% end %>
@ -177,16 +185,29 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
form={f} form={f}
disabled={@deployment_group_id != nil} disabled={@deployment_group_id != nil}
/> />
<AppComponents.docker_config_form_content hub={@hub} form={f} /> <div class="flex flex-col space-y-4">
<.radio_field
label="Deploy"
field={f[:deploy_all]}
options={[
{"false", "Only this notebook"},
{"true", "All notebooks in the current directory"}
]}
/>
<.radio_field
label="Base image"
field={f[:docker_tag]}
options={AppComponents.docker_tag_options()}
/>
</div>
</div> </div>
</.form> </.form>
<AppComponents.docker_instructions <div class="flex flex-col gap-4 pt-6">
hub={@hub} <div>
dockerfile={@dockerfile} <div class="flex items-end mb-1 gap-1">
dockerfile_config={apply_changes(@changeset)} <span class="text-sm text-gray-700 font-semibold">Dockerfile</span>
> <div class="grow" />
<:dockerfile_actions>
<.button <.button
color="gray" color="gray"
small small
@ -198,8 +219,73 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
<.remix_icon icon="save-line" /> <.remix_icon icon="save-line" />
<span>Save alongside notebook</span> <span>Save alongside notebook</span>
</.button> </.button>
</:dockerfile_actions> <.button
</AppComponents.docker_instructions> color="gray"
small
data-tooltip="Copied to clipboard"
type="button"
aria-label="copy to clipboard"
phx-click={
JS.dispatch("lb:clipcopy", to: "#dockerfile-source")
|> JS.transition("tooltip top", time: 2000)
}
>
<.remix_icon icon="clipboard-line" />
<span>Copy source</span>
</.button>
</div>
<.code_preview source_id="dockerfile-source" source={@dockerfile} language="dockerfile" />
</div>
<div class="text-gray-700">
To test the deployment locally, go the the notebook directory, save the Dockerfile, then run:
</div>
<.code_preview
source_id="dockerfile-cmd"
source={
~s'''
docker build -t my-app .
docker run --rm -p 8080:8080 -p 8081:8081 my-app
'''
}
language="text"
/>
<p class="text-gray-700 py-2">
You may additionally perform the following optional steps:
</p>
<ul class="text-gray-700 space-y-3">
<li :if={Hubs.Provider.type(@hub) == "team"} class="flex gap-2">
<div><.remix_icon icon="arrow-right-line" class="text-gray-900" /></div>
<span>
you may remove the default value for <code>TEAMS_KEY</code>
from your Dockerfile and set it as a build argument in your deployment
platform
</span>
</li>
<li :if={apply_changes(@changeset).clustering} class="flex gap-2">
<div><.remix_icon icon="arrow-right-line" class="text-gray-900" /></div>
<span>
you may set <code>LIVEBOOK_SECRET_KEY_BASE</code>
and <code>LIVEBOOK_COOKIE</code>
as runtime environment secrets in your deployment platform, to ensure their
values stay the same across deployments. If you do that, you can remove
the defaults from your Dockerfile
</span>
</li>
<li class="flex gap-2">
<div><.remix_icon icon="arrow-right-line" class="text-gray-900" /></div>
<span>
if you want to debug your deployed notebooks in production, you may
set the <code>LIVEBOOK_PASSWORD</code> environment variable with a
value of at least 12 characters of your choice
</span>
</li>
</ul>
</div>
</div> </div>
""" """
end end
@ -289,9 +375,14 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
end end
defp deployment_group_options(deployment_groups) do defp deployment_group_options(deployment_groups) do
for deployment_group <- [%{name: "none", id: nil}] ++ deployment_groups, [{"none", nil}] ++
do: {deployment_group.name, deployment_group.id} for deployment_group <- deployment_groups do
{"#{deployment_group.name} (#{mode(deployment_group.mode)})", deployment_group.id}
end end
end
defp mode(:online), do: "online"
defp mode(:offline), do: "airgapped"
defp deployment_group_help() do defp deployment_group_help() do
"Share deployment credentials, secrets, and configuration with deployment groups." "Share deployment credentials, secrets, and configuration with deployment groups."

View file

@ -62,13 +62,12 @@ defmodule LivebookWeb.SessionLive.AppInfoComponent do
</h3> </h3>
<div class="mt-2 flex flex-col gap-2"> <div class="mt-2 flex flex-col gap-2">
<%!-- TODO: Livebook Teams flow --%>
<.button <.button
color="blue" color="blue"
patch={ patch={
if Livebook.Notebook.AppSettings.valid?(@settings), if Livebook.Notebook.AppSettings.valid?(@settings),
do: ~p"/sessions/#{@session.id}/app-docker", do: ~p"/sessions/#{@session.id}/app-teams",
else: ~p"/sessions/#{@session.id}/settings/app?context=app-docker" else: ~p"/sessions/#{@session.id}/settings/app?context=app-teams"
} }
> >
<.remix_icon icon="rocket-line" /> Deploy with Livebook Teams <.remix_icon icon="rocket-line" /> Deploy with Livebook Teams

View file

@ -113,7 +113,7 @@ defmodule LivebookWeb.SessionLive.AppTeamsComponent do
<.label help={deployment_group_help()}> <.label help={deployment_group_help()}>
Deployment Group Deployment Group
</.label> </.label>
<span>No deployment groups available</span> <span>None configured</span>
</p> </p>
<% end %> <% end %>
<% end %> <% end %>

View file

@ -328,7 +328,7 @@ defmodule LivebookWeb.Integration.Hub.EditLiveTest do
assert view assert view
|> element("#secrets-form") |> element("#secrets-form")
|> render_submit(attrs) =~ |> render_submit(attrs) =~
"You are not authorized to perform this action, make sure you have the access or you are not in a Livebook Agent/Offline instance" "You are not authorized to perform this action, make sure you have the access and you are not in a Livebook App Server/Offline instance"
refute_receive {:secret_created, ^secret} refute_receive {:secret_created, ^secret}
refute secret in Livebook.Hubs.get_secrets(hub) refute secret in Livebook.Hubs.get_secrets(hub)
@ -356,7 +356,7 @@ defmodule LivebookWeb.Integration.Hub.EditLiveTest do
assert view assert view
|> element("#file-systems-form") |> element("#file-systems-form")
|> render_submit(attrs) =~ |> render_submit(attrs) =~
"You are not authorized to perform this action, make sure you have the access or you are not in a Livebook Agent/Offline instance" "You are not authorized to perform this action, make sure you have the access and you are not in a Livebook App Server/Offline instance"
refute_receive {:file_system_created, %{id: ^id}} refute_receive {:file_system_created, %{id: ^id}}
refute file_system in Livebook.Hubs.get_file_systems(hub) refute file_system in Livebook.Hubs.get_file_systems(hub)

View file

@ -457,7 +457,7 @@ defmodule LivebookWeb.Integration.SessionLiveTest do
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}/app-docker") {:ok, view, _} = live(conn, ~p"/sessions/#{session.id}/app-docker")
assert render(view) =~ "Deployment Group" assert render(view) =~ "Deployment Group"
assert render(view) =~ "No deployment groups available" assert render(view) =~ "None configured"
refute has_element?(view, "#select_deployment_group_form") refute has_element?(view, "#select_deployment_group_form")
end end