mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-10-06 19:46:00 +08:00
Simplify code that is no longer shared across views
This commit is contained in:
parent
4c6869d69c
commit
cb11b26cdc
9 changed files with 135 additions and 153 deletions
|
@ -309,7 +309,7 @@ defmodule Livebook.Teams.Requests do
|
|||
|
||||
{:ok, %{status: 401}} ->
|
||||
{: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 ->
|
||||
{:transport_error, @error_message}
|
||||
|
|
|
@ -82,30 +82,6 @@ defmodule LivebookWeb.AppComponents do
|
|||
)
|
||||
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 """
|
||||
Renders form fields for Deployment Group.
|
||||
"""
|
||||
|
@ -184,103 +160,18 @@ defmodule LivebookWeb.AppComponents do
|
|||
|
||||
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(zta_provider) do
|
||||
Enum.find(Livebook.Config.identity_providers(), &(&1.type == zta_provider))
|
||||
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 """
|
||||
Updates app list with the given apps event.
|
||||
"""
|
||||
|
|
|
@ -162,7 +162,8 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
|
|||
</h2>
|
||||
|
||||
<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
|
||||
environment variables using the <code>LB_</code> prefix.
|
||||
</p>
|
||||
|
@ -189,7 +190,7 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do
|
|||
</h2>
|
||||
|
||||
<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>
|
||||
|
||||
<.live_component
|
||||
|
|
|
@ -33,11 +33,11 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupComponent do
|
|||
<h3 class="font-semibold"><%= @deployment_group.name %></h3>
|
||||
<%= 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">
|
||||
<%= @deployment_group.mode %>
|
||||
Online
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="bg-red-100 text-red-800 text-xs px-2.5 py-0.5 rounded cursor-default">
|
||||
<%= @deployment_group.mode %>
|
||||
Airgapped
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
@ -123,9 +123,8 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
|
|||
defp content(assigns) do
|
||||
~H"""
|
||||
<div class="flex flex-col gap-4">
|
||||
<p class="text-gray-700">
|
||||
You can deploy this app in the cloud using Docker. To do that, configure
|
||||
the deployment and then use the generated Dockerfile.
|
||||
<p class="text-gray-700 pb-4">
|
||||
Choose your deployment settings and then deploy your notebook using the generated Dockerfile.
|
||||
</p>
|
||||
|
||||
<div class="flex gap-12">
|
||||
|
@ -158,7 +157,16 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
|
|||
<.label help={deployment_group_help()}>
|
||||
Deployment Group
|
||||
</.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>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
@ -177,29 +185,107 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
|
|||
form={f}
|
||||
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>
|
||||
</.form>
|
||||
|
||||
<AppComponents.docker_instructions
|
||||
hub={@hub}
|
||||
dockerfile={@dockerfile}
|
||||
dockerfile_config={apply_changes(@changeset)}
|
||||
>
|
||||
<:dockerfile_actions>
|
||||
<.button
|
||||
color="gray"
|
||||
small
|
||||
type="button"
|
||||
aria-label="save dockerfile alongside the notebook"
|
||||
phx-click="save_dockerfile"
|
||||
phx-target={@myself}
|
||||
>
|
||||
<.remix_icon icon="save-line" />
|
||||
<span>Save alongside notebook</span>
|
||||
</.button>
|
||||
</:dockerfile_actions>
|
||||
</AppComponents.docker_instructions>
|
||||
<div class="flex flex-col gap-4 pt-6">
|
||||
<div>
|
||||
<div class="flex items-end mb-1 gap-1">
|
||||
<span class="text-sm text-gray-700 font-semibold">Dockerfile</span>
|
||||
<div class="grow" />
|
||||
<.button
|
||||
color="gray"
|
||||
small
|
||||
type="button"
|
||||
aria-label="save dockerfile alongside the notebook"
|
||||
phx-click="save_dockerfile"
|
||||
phx-target={@myself}
|
||||
>
|
||||
<.remix_icon icon="save-line" />
|
||||
<span>Save alongside notebook</span>
|
||||
</.button>
|
||||
<.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={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>
|
||||
"""
|
||||
end
|
||||
|
@ -289,10 +375,15 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
|
|||
end
|
||||
|
||||
defp deployment_group_options(deployment_groups) do
|
||||
for deployment_group <- [%{name: "none", id: nil}] ++ deployment_groups,
|
||||
do: {deployment_group.name, deployment_group.id}
|
||||
[{"none", nil}] ++
|
||||
for deployment_group <- deployment_groups do
|
||||
{"#{deployment_group.name} (#{mode(deployment_group.mode)})", deployment_group.id}
|
||||
end
|
||||
end
|
||||
|
||||
defp mode(:online), do: "online"
|
||||
defp mode(:offline), do: "airgapped"
|
||||
|
||||
defp deployment_group_help() do
|
||||
"Share deployment credentials, secrets, and configuration with deployment groups."
|
||||
end
|
||||
|
|
|
@ -62,13 +62,12 @@ defmodule LivebookWeb.SessionLive.AppInfoComponent do
|
|||
</h3>
|
||||
|
||||
<div class="mt-2 flex flex-col gap-2">
|
||||
<%!-- TODO: Livebook Teams flow --%>
|
||||
<.button
|
||||
color="blue"
|
||||
patch={
|
||||
if Livebook.Notebook.AppSettings.valid?(@settings),
|
||||
do: ~p"/sessions/#{@session.id}/app-docker",
|
||||
else: ~p"/sessions/#{@session.id}/settings/app?context=app-docker"
|
||||
do: ~p"/sessions/#{@session.id}/app-teams",
|
||||
else: ~p"/sessions/#{@session.id}/settings/app?context=app-teams"
|
||||
}
|
||||
>
|
||||
<.remix_icon icon="rocket-line" /> Deploy with Livebook Teams
|
||||
|
|
|
@ -113,7 +113,7 @@ defmodule LivebookWeb.SessionLive.AppTeamsComponent do
|
|||
<.label help={deployment_group_help()}>
|
||||
Deployment Group
|
||||
</.label>
|
||||
<span>No deployment groups available</span>
|
||||
<span>None configured</span>
|
||||
</p>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -328,7 +328,7 @@ defmodule LivebookWeb.Integration.Hub.EditLiveTest do
|
|||
assert view
|
||||
|> element("#secrets-form")
|
||||
|> 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 secret in Livebook.Hubs.get_secrets(hub)
|
||||
|
@ -356,7 +356,7 @@ defmodule LivebookWeb.Integration.Hub.EditLiveTest do
|
|||
assert view
|
||||
|> element("#file-systems-form")
|
||||
|> 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 file_system in Livebook.Hubs.get_file_systems(hub)
|
||||
|
|
|
@ -457,7 +457,7 @@ defmodule LivebookWeb.Integration.SessionLiveTest do
|
|||
{:ok, view, _} = live(conn, ~p"/sessions/#{session.id}/app-docker")
|
||||
|
||||
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")
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue