Warn on Dockerfile when deploying a directory with personal hub and it has file systems (#2281)

This commit is contained in:
Jonatan Kłosko 2023-10-17 20:28:37 +02:00 committed by GitHub
parent a643307d52
commit d40c004e83
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 20 deletions

View file

@ -59,7 +59,7 @@ defmodule Livebook.Hubs.Dockerfile do
image_envs = format_envs(base_image.env) image_envs = format_envs(base_image.env)
hub_type = Hubs.Provider.type(hub) hub_type = Hubs.Provider.type(hub)
used_secrets = used_secrets(config, hub, secrets, hub_secrets) |> Enum.sort_by(& &1.name) used_secrets = used_hub_secrets(config, hub_secrets, secrets) |> Enum.sort_by(& &1.name)
hub_config = format_hub_config(hub_type, config, hub, hub_file_systems, used_secrets) hub_config = format_hub_config(hub_type, config, hub, hub_file_systems, used_secrets)
apps_config = """ apps_config = """
@ -202,11 +202,29 @@ defmodule Livebook.Hubs.Dockerfile do
|> Livebook.Teams.encrypt(secret_key) |> Livebook.Teams.encrypt(secret_key)
end end
defp used_secrets(config, hub, secrets, hub_secrets) do defp used_hub_secrets(config, hub_secrets, secrets) do
if config.deploy_all do if config.deploy_all do
hub_secrets hub_secrets
else else
for {_, secret} <- secrets, secret.hub_id == hub.id, do: secret Enum.filter(hub_secrets, fn hub_secret ->
if secret = secrets[hub_secret.name] do
secret.hub_id == hub_secret.hub_id
end
end)
end
end
defp used_hub_file_systems(config, hub_file_systems, file_entries) do
if config.deploy_all do
hub_file_systems
else
file_entry_file_system_ids =
for entry <- file_entries,
entry.type == :file,
do: entry.file.file_system_id,
into: MapSet.new()
Enum.filter(hub_file_systems, &(&1.id in file_entry_file_system_ids))
end end
end end
@ -223,11 +241,12 @@ defmodule Livebook.Hubs.Dockerfile do
config(), config(),
Hubs.Provider.t(), Hubs.Provider.t(),
list(Livebook.Secrets.Secret.t()), list(Livebook.Secrets.Secret.t()),
list(Livebook.FileSystem.t()),
Livebook.Notebook.AppSettings.t(), Livebook.Notebook.AppSettings.t(),
list(Livebook.Notebook.file_entry()), list(Livebook.Notebook.file_entry()),
list(Livebook.Session.Data.secrets()) list(Livebook.Session.Data.secrets())
) :: list(String.t()) ) :: list(String.t())
def warnings(config, hub, hub_secrets, app_settings, file_entries, secrets) do def warnings(config, hub, hub_secrets, hub_file_systems, app_settings, file_entries, secrets) do
common_warnings = common_warnings =
[ [
if Livebook.Session.Data.session_secrets(secrets, hub.id) != [] do if Livebook.Session.Data.session_secrets(secrets, hub.id) != [] do
@ -239,14 +258,18 @@ defmodule Livebook.Hubs.Dockerfile do
hub_warnings = hub_warnings =
case Hubs.Provider.type(hub) do case Hubs.Provider.type(hub) do
"personal" -> "personal" ->
used_hub_secrets = used_hub_secrets(config, hub_secrets, secrets)
used_hub_file_systems = used_hub_file_systems(config, hub_file_systems, file_entries)
[ [
if used_secrets(config, hub, secrets, hub_secrets) != [] do if used_hub_secrets != [] do
"You are deploying an app with secrets and the secrets are included in the Dockerfile" <> "You are deploying an app with secrets and the secrets are included in the Dockerfile" <>
" as environment variables. If someone else deploys this app, they must also set the" <> " as environment variables. If someone else deploys this app, they must also set the" <>
" same secrets. Use Livebook Teams to automatically encrypt and synchronize secrets" <> " same secrets. Use Livebook Teams to automatically encrypt and synchronize secrets" <>
" across your team and deployments." " across your team and deployments."
end, end,
if module = find_hub_file_system(file_entries) do if used_hub_file_systems != [] do
%module{} = hd(used_hub_file_systems)
name = LivebookWeb.FileSystemHelpers.file_system_name(module) name = LivebookWeb.FileSystemHelpers.file_system_name(module)
"The #{name} file storage, defined in your personal hub, will not be available in the Docker image." <> "The #{name} file storage, defined in your personal hub, will not be available in the Docker image." <>
@ -274,11 +297,4 @@ defmodule Livebook.Hubs.Dockerfile do
Enum.reject(common_warnings ++ hub_warnings, &is_nil/1) Enum.reject(common_warnings ++ hub_warnings, &is_nil/1)
end end
defp find_hub_file_system(file_entries) do
Enum.find_value(file_entries, fn entry ->
entry.type == :file && entry.file.file_system_module != FileSystem.Local &&
entry.file.file_system_module
end)
end
end end

View file

@ -181,7 +181,15 @@ defmodule LivebookWeb.SessionLive.AppDockerComponent do
) )
warnings = warnings =
Hubs.Dockerfile.warnings(config, hub, hub_secrets, app_settings, file_entries, secrets) Hubs.Dockerfile.warnings(
config,
hub,
hub_secrets,
hub_file_systems,
app_settings,
file_entries,
secrets
)
assign(socket, dockerfile: dockerfile, warnings: warnings) assign(socket, dockerfile: dockerfile, warnings: warnings)
end end

View file

@ -206,7 +206,7 @@ defmodule Livebook.Hubs.DockerfileTest do
session_secret = %Secret{name: "SESSION", value: "test", hub_id: nil} session_secret = %Secret{name: "SESSION", value: "test", hub_id: nil}
secrets = %{"SESSION" => session_secret} secrets = %{"SESSION" => session_secret}
assert [warning] = Dockerfile.warnings(config, hub, [], app_settings, [], secrets) assert [warning] = Dockerfile.warnings(config, hub, [], [], app_settings, [], secrets)
assert warning =~ "The notebook uses session secrets" assert warning =~ "The notebook uses session secrets"
end end
@ -220,7 +220,9 @@ defmodule Livebook.Hubs.DockerfileTest do
hub_secrets = [secret] hub_secrets = [secret]
secrets = %{"TEST" => secret} secrets = %{"TEST" => secret}
assert [warning] = Dockerfile.warnings(config, hub, hub_secrets, app_settings, [], secrets) assert [warning] =
Dockerfile.warnings(config, hub, hub_secrets, [], app_settings, [], secrets)
assert warning =~ "secrets are included in the Dockerfile" assert warning =~ "secrets are included in the Dockerfile"
end end
@ -230,12 +232,28 @@ defmodule Livebook.Hubs.DockerfileTest do
app_settings = Livebook.Notebook.AppSettings.new() app_settings = Livebook.Notebook.AppSettings.new()
file_system = Livebook.Factory.build(:fs_s3) file_system = Livebook.Factory.build(:fs_s3)
file_systems = [file_system]
file_entries = [ file_entries = [
%{type: :file, file: Livebook.FileSystem.File.new(file_system, "/data.csv")} %{type: :file, file: Livebook.FileSystem.File.new(file_system, "/data.csv")}
] ]
assert [warning] = Dockerfile.warnings(config, hub, [], app_settings, file_entries, %{}) assert [warning] =
Dockerfile.warnings(config, hub, [], file_systems, app_settings, file_entries, %{})
assert warning =~
"The S3 file storage, defined in your personal hub, will not be available in the Docker image"
end
test "warns when deploying a directory in personal hub and it has any file systems" do
config = dockerfile_config(%{deploy_all: true})
hub = personal_hub()
app_settings = Livebook.Notebook.AppSettings.new()
file_system = Livebook.Factory.build(:fs_s3)
file_systems = [file_system]
assert [warning] = Dockerfile.warnings(config, hub, [], file_systems, app_settings, [], %{})
assert warning =~ assert warning =~
"The S3 file storage, defined in your personal hub, will not be available in the Docker image" "The S3 file storage, defined in your personal hub, will not be available in the Docker image"
@ -246,7 +264,7 @@ defmodule Livebook.Hubs.DockerfileTest do
hub = personal_hub() hub = personal_hub()
app_settings = %{Livebook.Notebook.AppSettings.new() | access_type: :public} app_settings = %{Livebook.Notebook.AppSettings.new() | access_type: :public}
assert [warning] = Dockerfile.warnings(config, hub, [], app_settings, [], %{}) assert [warning] = Dockerfile.warnings(config, hub, [], [], app_settings, [], %{})
assert warning =~ "This app has no password configuration" assert warning =~ "This app has no password configuration"
end end
@ -255,12 +273,12 @@ defmodule Livebook.Hubs.DockerfileTest do
hub = team_hub() hub = team_hub()
app_settings = %{Livebook.Notebook.AppSettings.new() | access_type: :public} app_settings = %{Livebook.Notebook.AppSettings.new() | access_type: :public}
assert [warning] = Dockerfile.warnings(config, hub, [], app_settings, [], %{}) assert [warning] = Dockerfile.warnings(config, hub, [], [], app_settings, [], %{})
assert warning =~ "This app has no password configuration" assert warning =~ "This app has no password configuration"
config = %{config | zta_provider: :cloudflare, zta_key: "key"} config = %{config | zta_provider: :cloudflare, zta_key: "key"}
assert [] = Dockerfile.warnings(config, hub, [], app_settings, [], %{}) assert [] = Dockerfile.warnings(config, hub, [], [], app_settings, [], %{})
end end
end end