Support setting node and distribution using environment vars (#1672)

This commit is contained in:
Zach Allaun 2023-02-01 12:22:49 -08:00 committed by GitHub
parent 25b4043dc7
commit 8f92661918
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 85 additions and 9 deletions

View file

@ -164,6 +164,9 @@ The following environment variables configure Livebook:
* LIVEBOOK_APP_SERVICE_URL - sets the application url to manage this
Livebook instance within the cloud provider platform.
* LIVEBOOK_BASE_URL_PATH - sets the base url path the web application is served on.
Useful when deploying behind a reverse proxy.
* LIVEBOOK_COOKIE - sets the cookie for running Livebook in a cluster.
Defaults to a random string that is generated on boot.
@ -175,6 +178,10 @@ The following environment variables configure Livebook:
"standalone" (Elixir standalone), "attached:NODE:COOKIE" (Attached node)
or "embedded" (Embedded). Defaults to "standalone".
* LIVEBOOK_DISTRIBUTION - sets the node distribution for running Livebook in a
cluster. Must be "name" (long names) or "sname" (short names). Note that this
sets RELEASE_DISTRIBUTION if present when creating a release. Defaults to "sname".
* LIVEBOOK_FORCE_SSL_HOST - sets a host to redirect to if the request is not over HTTP.
Note it does not apply when accessing Livebook via localhost. Defaults to nil.
@ -192,8 +199,8 @@ The following environment variables configure Livebook:
* LIVEBOOK_IP - sets the ip address to start the web application on.
Must be a valid IPv4 or IPv6 address.
* LIVEBOOK_BASE_URL_PATH - sets the base url path the web application is served on.
Useful when deploying behind a reverse proxy.
* LIVEBOOK_NODE - sets the node name for running Livebook in a cluster. Note that
this sets RELEASE_NODE if present when creating a release.
* LIVEBOOK_PASSWORD - sets a password that must be used to access Livebook.
Must be at least 12 characters. Defaults to token authentication.
@ -224,11 +231,6 @@ The following environment variables configure Livebook:
<!-- Environment variables -->
If running Livebook as a Docker image or an Elixir release, [the environment
variables used by Elixir releases are also available](
https://hexdocs.pm/mix/Mix.Tasks.Release.html#module-environment-variables).
The notables ones are `RELEASE_NODE` and `RELEASE_DISTRIBUTION`.
If running Livebook via the command line, run `livebook server --help` to see
all CLI-specific options.

View file

@ -160,6 +160,10 @@ defmodule Livebook do
Livebook.Config.cookie!("RELEASE_COOKIE") ||
Livebook.Utils.random_cookie()
if node = Livebook.Config.node!("LIVEBOOK_NODE", "LIVEBOOK_DISTRIBUTION") do
config :livebook, :node, node
end
if app_service_name = Livebook.Config.app_service_name!("LIVEBOOK_APP_SERVICE_NAME") do
config :livebook, :app_service_name, app_service_name

View file

@ -291,6 +291,25 @@ defmodule Livebook.Config do
end
end
@doc """
Parses node and distribution type from env.
"""
def node!(node_env, distribution_env) do
case {System.get_env(node_env), System.get_env(distribution_env, "sname")} do
{nil, _} ->
nil
{name, "name"} ->
{:longnames, String.to_atom(name)}
{sname, "sname"} ->
{:shortnames, String.to_atom(sname)}
{_, other} ->
abort!(~s(#{distribution_env} must be one of "name" or "sname", got "#{other}"))
end
end
@doc """
Parses and validates the password from env.
"""

View file

@ -131,7 +131,7 @@ defmodule Livebook.MixProject do
defp releases do
[
livebook: [
include_executables_for: [:unix],
include_executables_for: [:unix, :windows],
include_erts: false,
rel_templates_path: "rel/server",
steps: [:assemble, &remove_cookie/1]

View file

@ -1,4 +1,6 @@
if defined LIVEBOOK_NODE set RELEASE_NODE="!LIVEBOOK_NODE!"
if not defined RELEASE_NODE set RELEASE_NODE=livebook_server
if defined LIVEBOOK_DISTRIBUTION set RELEASE_DISTRIBUTION="!LIVEBOOK_DISTRIBUTION!"
set RELEASE_MODE=interactive
set cookie_path="!RELEASE_ROOT!\releases\COOKIE"

View file

@ -1,4 +1,5 @@
export RELEASE_NODE="${RELEASE_NODE:-livebook_server}"
export RELEASE_NODE=${LIVEBOOK_NODE:-${RELEASE_NODE:-livebook_server}}
export RELEASE_DISTRIBUTION=${LIVEBOOK_DISTRIBUTION:-${RELEASE_DISTRIBUTION:-sname}}
export RELEASE_MODE=interactive
cookie_path="${RELEASE_ROOT}/releases/COOKIE"

View file

@ -0,0 +1,48 @@
defmodule Livebook.ConfigTest do
use ExUnit.Case, async: true
alias Livebook.Config
describe "node!/1" do
test "parses longnames" do
with_env([TEST_LIVEBOOK_NODE: "test@::1", TEST_LIVEBOOK_DISTRIBUTION: "name"], fn ->
assert Config.node!("TEST_LIVEBOOK_NODE", "TEST_LIVEBOOK_DISTRIBUTION") ==
{:longnames, :"test@::1"}
end)
end
test "parses shortnames" do
with_env([TEST_LIVEBOOK_NODE: "test", TEST_LIVEBOOK_DISTRIBUTION: "sname"], fn ->
assert Config.node!("TEST_LIVEBOOK_NODE", "TEST_LIVEBOOK_DISTRIBUTION") ==
{:shortnames, :test}
end)
end
test "parses shortnames by default" do
with_env([TEST_LIVEBOOK_NODE: "test", TEST_LIVEBOOK_DISTRIBUTION: nil], fn ->
assert Config.node!("TEST_LIVEBOOK_NODE", "TEST_LIVEBOOK_DISTRIBUTION") ==
{:shortnames, :test}
end)
end
test "returns nil if node is not set" do
with_env([TEST_LIVEBOOK_NODE: nil, TEST_LIVEBOOK_DISTRIBUTION: "name"], fn ->
assert Config.node!("TEST_LIVEBOOK_NODE", "TEST_LIVEBOOK_DISTRIBUTION") == nil
end)
end
end
defp with_env(env_vars, fun) do
existing =
Enum.map(env_vars, fn {env, _value} ->
{env, env |> to_string() |> System.get_env()}
end)
try do
System.put_env(env_vars)
fun.()
after
System.put_env(existing)
end
end
end