diff --git a/lib/livebook/teams/requests.ex b/lib/livebook/teams/requests.ex index fdf8bbf46..32b89dabc 100644 --- a/lib/livebook/teams/requests.ex +++ b/lib/livebook/teams/requests.ex @@ -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} diff --git a/lib/livebook_web/components/app_components.ex b/lib/livebook_web/components/app_components.ex index 7e88482f6..56b5e8a37 100644 --- a/lib/livebook_web/components/app_components.ex +++ b/lib/livebook_web/components/app_components.ex @@ -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""" -
- <.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()} /> -
- """ - 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""" -
-
-
- Dockerfile -
- <%= 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" /> - Copy source - -
- - <.code_preview source_id="dockerfile-source" source={@dockerfile} language="dockerfile" /> -
- -
- To test the deployment locally, go the the notebook directory, save the Dockerfile, then run: -
- - <.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" - /> - -

- You may additionally perform the following optional steps: -

- - -
- """ - 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. """ diff --git a/lib/livebook_web/live/hub/edit/team_component.ex b/lib/livebook_web/live/hub/edit/team_component.ex index dd2990100..ce07d62a8 100644 --- a/lib/livebook_web/live/hub/edit/team_component.ex +++ b/lib/livebook_web/live/hub/edit/team_component.ex @@ -162,7 +162,8 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do

- 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 LB_ prefix.

@@ -189,7 +190,7 @@ defmodule LivebookWeb.Hub.Edit.TeamComponent do

- File storages are used to store notebooks and their files. + File storages are used to store notebooks and their files across your whole team.

<.live_component diff --git a/lib/livebook_web/live/hub/teams/deployment_group_component.ex b/lib/livebook_web/live/hub/teams/deployment_group_component.ex index 007253432..3002da2a3 100644 --- a/lib/livebook_web/live/hub/teams/deployment_group_component.ex +++ b/lib/livebook_web/live/hub/teams/deployment_group_component.ex @@ -33,11 +33,11 @@ defmodule LivebookWeb.Hub.Teams.DeploymentGroupComponent do

<%= @deployment_group.name %>

<%= if @deployment_group.mode == :online do %>
- <%= @deployment_group.mode %> + Online
<% else %>
- <%= @deployment_group.mode %> + Airgapped
<% end %>
diff --git a/lib/livebook_web/live/session_live/app_docker_component.ex b/lib/livebook_web/live/session_live/app_docker_component.ex index 6ab0ec7e5..0fb5ed00d 100644 --- a/lib/livebook_web/live/session_live/app_docker_component.ex +++ b/lib/livebook_web/live/session_live/app_docker_component.ex @@ -123,9 +123,8 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do defp content(assigns) do ~H"""
-

- You can deploy this app in the cloud using Docker. To do that, configure - the deployment and then use the generated Dockerfile. +

+ Choose your deployment settings and then deploy your notebook using the generated Dockerfile.

@@ -158,7 +157,16 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do <.label help={deployment_group_help()}> Deployment Group - No deployment groups available + + None configured + <.link + navigate={~p"/hub/#{@hub.id}/groups/new"} + target="_blank" + class="pl-3 text-blue-600 font-semibold" + > + + add new + +

<% end %> <% end %> @@ -177,29 +185,107 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do form={f} disabled={@deployment_group_id != nil} /> - +
+ <.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()} + /> +
- - <: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" /> - Save alongside notebook - - - +
+
+
+ Dockerfile +
+ <.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" /> + Save alongside notebook + + <.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" /> + Copy source + +
+ + <.code_preview source_id="dockerfile-source" source={@dockerfile} language="dockerfile" /> +
+ +
+ To test the deployment locally, go the the notebook directory, save the Dockerfile, then run: +
+ + <.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" + /> + +

+ You may additionally perform the following optional steps: +

+ +
    +
  • +
    <.remix_icon icon="arrow-right-line" class="text-gray-900" />
    + + you may remove the default value for TEAMS_KEY + from your Dockerfile and set it as a build argument in your deployment + platform + +
  • +
  • +
    <.remix_icon icon="arrow-right-line" class="text-gray-900" />
    + + you may set LIVEBOOK_SECRET_KEY_BASE + and LIVEBOOK_COOKIE + 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 + +
  • +
  • +
    <.remix_icon icon="arrow-right-line" class="text-gray-900" />
    + + if you want to debug your deployed notebooks in production, you may + set the LIVEBOOK_PASSWORD environment variable with a + value of at least 12 characters of your choice + +
  • +
+
""" 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 diff --git a/lib/livebook_web/live/session_live/app_info_component.ex b/lib/livebook_web/live/session_live/app_info_component.ex index be3ec84c3..424201184 100644 --- a/lib/livebook_web/live/session_live/app_info_component.ex +++ b/lib/livebook_web/live/session_live/app_info_component.ex @@ -62,13 +62,12 @@ defmodule LivebookWeb.SessionLive.AppInfoComponent do
- <%!-- 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 diff --git a/lib/livebook_web/live/session_live/app_teams_component.ex b/lib/livebook_web/live/session_live/app_teams_component.ex index 599004363..cb2fc0e94 100644 --- a/lib/livebook_web/live/session_live/app_teams_component.ex +++ b/lib/livebook_web/live/session_live/app_teams_component.ex @@ -113,7 +113,7 @@ defmodule LivebookWeb.SessionLive.AppTeamsComponent do <.label help={deployment_group_help()}> Deployment Group - No deployment groups available + None configured

<% end %> <% end %> diff --git a/test/livebook_teams/web/hub/edit_live_test.exs b/test/livebook_teams/web/hub/edit_live_test.exs index c176ed58a..7161851ea 100644 --- a/test/livebook_teams/web/hub/edit_live_test.exs +++ b/test/livebook_teams/web/hub/edit_live_test.exs @@ -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) diff --git a/test/livebook_teams/web/session_live_test.exs b/test/livebook_teams/web/session_live_test.exs index f93dfe4e3..9fcc7e72a 100644 --- a/test/livebook_teams/web/session_live_test.exs +++ b/test/livebook_teams/web/session_live_test.exs @@ -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