Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move more runtime config to Application module #447

Draft
wants to merge 6 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ config :asciinema, Asciinema.Repo,
database: "asciinema_development",
stacktrace: true,
show_sensitive_data_on_connection_error: true,
pool_size: 10
pool_size: 11

secret_key_base = "60BnXnzGGwwiZj91YA9XYKF9BCiM7lQ/1um8VXcWWLSdUp9OcPZV6YnQv7eFTYSY"

Expand Down
82 changes: 0 additions & 82 deletions config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,81 +8,11 @@ import Config

env = &System.get_env/1

if env.("PHX_SERVER") do
config :asciinema, AsciinemaWeb.Endpoint, server: true
config :asciinema, AsciinemaWeb.Admin.Endpoint, server: true
end

if config_env() == :prod do
database_url =
System.get_env("DATABASE_URL") ||
raise """
environment variable DATABASE_URL is missing.
For example: ecto://USER:PASS@HOST/DATABASE
"""

config :asciinema, Asciinema.Repo, url: database_url
end

if config_env() in [:prod, :dev] do
if secret_key_base = env.("SECRET_KEY_BASE") do
config :asciinema, AsciinemaWeb.Endpoint, secret_key_base: secret_key_base
config :asciinema, AsciinemaWeb.Admin.Endpoint, secret_key_base: secret_key_base
config :asciinema, Asciinema.Accounts, secret: secret_key_base
end

if port = env.("PORT") do
config :asciinema, AsciinemaWeb.Endpoint, http: [port: String.to_integer(port)]
end

if url_scheme = env.("URL_SCHEME") do
config :asciinema, AsciinemaWeb.Endpoint, url: [scheme: url_scheme]

case url_scheme do
"http" ->
config :asciinema, AsciinemaWeb.Endpoint, url: [port: 80]

"https" ->
config :asciinema, AsciinemaWeb.Endpoint, url: [port: 443]

_ ->
:ok
end
end

if url_host = env.("URL_HOST") do
config :asciinema, AsciinemaWeb.Endpoint, url: [host: url_host]
end

if url_path = env.("URL_PATH") do
config :asciinema, AsciinemaWeb.Endpoint, url: [path: url_path]
# this requires path prefix stripping at reverse proxy (nginx) level
end

if url_port = env.("URL_PORT") do
config :asciinema, AsciinemaWeb.Endpoint, url: [port: String.to_integer(url_port)]
end

if env.("ADMIN_BIND_ALL") do
config :asciinema, AsciinemaWeb.Admin.Endpoint, http: [ip: {0, 0, 0, 0}]
end

if port = env.("ADMIN_PORT") do
config :asciinema, AsciinemaWeb.Admin.Endpoint, http: [port: String.to_integer(port)]
end

if url_scheme = env.("ADMIN_URL_SCHEME") do
config :asciinema, AsciinemaWeb.Admin.Endpoint, url: [scheme: url_scheme]
end

if url_host = env.("ADMIN_URL_HOST") do
config :asciinema, AsciinemaWeb.Admin.Endpoint, url: [host: url_host]
end

if url_port = env.("ADMIN_URL_PORT") do
config :asciinema, AsciinemaWeb.Admin.Endpoint, url: [port: String.to_integer(url_port)]
end

if ip_limit = env.("IP_RATE_LIMIT") do
config :asciinema, AsciinemaWeb.PlugAttack,
ip_limit: String.to_integer(ip_limit),
Expand Down Expand Up @@ -133,14 +63,6 @@ if config_env() in [:prod, :dev] do
end
end

if db_pool_size = env.("DB_POOL_SIZE") do
config :asciinema, Asciinema.Repo, pool_size: String.to_integer(db_pool_size)
end

if env.("ECTO_IPV6") in ~w(true 1) do
config :asciinema, Asciinema.Repo, socket_options: [:inet6]
end

if smtp_host = env.("SMTP_HOST") do
config :asciinema, Asciinema.Emails.Mailer,
adapter: Swoosh.Adapters.SMTP,
Expand Down Expand Up @@ -204,10 +126,6 @@ if config_env() in [:prod, :dev] do
config :asciinema, :unclaimed_recording_ttl, ttls
end

if String.downcase("#{env.("CRON")}") in ["0", "false", "no"] do
config :asciinema, Oban, plugins: [{Oban.Plugins.Cron, crontab: []}]
end

if env.("SIGN_UP_DISABLED") in ["1", "true"] do
config :asciinema, Asciinema.Accounts, sign_up_enabled?: false
end
Expand Down
4 changes: 0 additions & 4 deletions config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ config :asciinema, Asciinema.Repo,
pool: Ecto.Adapters.SQL.Sandbox,
pool_size: 10

if db_url = System.get_env("TEST_DATABASE_URL") do
System.put_env("DATABASE_URL", db_url)
end

# In test we don't send emails.
config :asciinema, Asciinema.Emails.Mailer, adapter: Swoosh.Adapters.Test

Expand Down
131 changes: 124 additions & 7 deletions lib/asciinema/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,24 @@ defmodule Asciinema.Application do
def start(_type, _args) do
:ok = Oban.Telemetry.attach_default_logger()
:ok = Asciinema.ObanErrorReporter.configure()

topologies = Application.get_env(:libcluster, :topologies, [])
# rr = take_app_env(Asciinema.Repo)
rr = Application.fetch_env!(:asciinema, Asciinema.Repo)
IO.inspect(rr, label: "rr")

# List all child processes to be supervised
children = [
# Start task supervisor
{Task.Supervisor, name: Asciinema.TaskSupervisor},
# Start cluster supervisor
{Cluster.Supervisor, [topologies, [name: Asciinema.ClusterSupervisor]]},
{Cluster.Supervisor, [cluster_topologies(), [name: Asciinema.ClusterSupervisor]]},
# Start the PubSub system
{Phoenix.PubSub, [name: Asciinema.PubSub, adapter: Phoenix.PubSub.PG2]},
# Start live stream viewer tracker
{Asciinema.Streaming.ViewerTracker, [pubsub_server: Asciinema.PubSub]},
# Start telemetry reporters
Asciinema.Telemetry,
# Start the Ecto repository
Asciinema.Repo,
{Asciinema.Repo, rr},
# Start PNG generator poolboy pool
:poolboy.child_spec(:worker, Asciinema.PngGenerator.Rsvg.poolboy_config(), []),
# Start Oban
Expand All @@ -37,9 +38,9 @@ defmodule Asciinema.Application do
# Start rate limiter
{PlugAttack.Storage.Ets, name: AsciinemaWeb.PlugAttack.Storage, clean_period: 60_000},
# Start the public endpoint
AsciinemaWeb.Endpoint,
{AsciinemaWeb.Endpoint, public_endpoint_config()},
# Start the admin endpoint
AsciinemaWeb.Admin.Endpoint
{AsciinemaWeb.Admin.Endpoint, admin_endpoint_config()}
]

# See https://hexdocs.pm/elixir/Supervisor.html
Expand All @@ -56,7 +57,123 @@ defmodule Asciinema.Application do
:ok
end

defp cluster_topologies, do: Application.get_env(:libcluster, :topologies, [])

defp oban_config do
Application.fetch_env!(:asciinema, Oban)
defaults = Application.fetch_env!(:asciinema, Oban)

config =
if String.downcase("#{System.get_env("CRON")}") in ["0", "false"] do
deep_merge(defaults, plugins: [{Oban.Plugins.Cron, crontab: []}])
else
defaults
end

if System.get_env("INSPECT_CONFIG") do
IO.inspect(config, label: "oban config")
end

config
end

defp public_endpoint_config do
defaults = take_app_env(AsciinemaWeb.Endpoint)

http = put_option([], :port, "PORT", &String.to_integer/1)

url =
[]
|> put_option(:scheme, "URL_SCHEME")
|> put_option(:host, "URL_HOST")
|> put_option(:port, "URL_PORT", &String.to_integer/1)
|> put_option(:path, "URL_PATH")

url =
case Keyword.get(url, :scheme) do
"http" -> Keyword.put_new(url, :port, 80)
"https" -> Keyword.put_new(url, :port, 443)
nil -> url
end

overrides =
[]
|> put_option(:server, "PHX_SERVER", fn _ -> true end)
|> put_option(:secret_key_base, "SECRET_KEY_BASE")
|> Keyword.merge(http: http, url: url)

config = deep_merge(defaults, overrides)

if System.get_env("INSPECT_CONFIG") do
IO.inspect(config, label: "public endpoint config")
end

config
end

defp admin_endpoint_config do
defaults = take_app_env(AsciinemaWeb.Admin.Endpoint)

http =
[]
|> put_option(:port, "ADMIN_PORT", &String.to_integer/1)
|> put_option(:ip, "ADMIN_BIND_ALL", fn _ -> {0, 0, 0, 0} end)

url =
[]
|> put_option(:scheme, "ADMIN_URL_SCHEME")
|> put_option(:host, "ADMIN_URL_HOST")
|> put_option(:port, "ADMIN_URL_PORT", &String.to_integer/1)

overrides =
[]
|> put_option(:server, "PHX_SERVER", fn _ -> true end)
|> put_option(:secret_key_base, "SECRET_KEY_BASE")
|> Keyword.merge(http: http, url: url)

config = deep_merge(defaults, overrides)

if System.get_env("INSPECT_CONFIG") do
IO.inspect(config, label: "admin endpoint config")
end

config
end

defp take_app_env(app \\ :asciinema, key) do
env = Application.get_env(app, key)
Application.delete_env(app, key)
Application.put_env(app, key, [])

env
end

defp put_option(opts, key, var, coerce \\ nil, default \\ :none)

defp put_option(opts, key, var, nil, default),
do: put_option(opts, key, var, fn value -> value end, default)

defp put_option(opts, key, var, coerce, default) do
case System.get_env(var) do
nil ->
case default do
:none -> opts
value -> Keyword.put(opts, key, value)
end

value ->
Keyword.put(opts, key, coerce.(value))
end
end

def deep_merge(original, overrides) do
Keyword.merge(original, overrides, &on_conflict/3)
end

defp on_conflict(_key, a, b) do
if Keyword.keyword?(a) and Keyword.keyword?(b) do
deep_merge(a, b)
else
b
end
end
end
20 changes: 20 additions & 0 deletions lib/asciinema/repo.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@ defmodule Asciinema.Repo do

use Scrivener, page_size: 10

def init(_type, config) do
config = Keyword.put(config, :url, System.get_env("DATABASE_URL"))

config =
if pool_size = System.get_env("DB_POOL_SIZE") do
Keyword.put(config, :pool_size, String.to_integer(pool_size))
else
config
end

config =
if System.get_env("ECTO_IPV6") in ~w(true 1) do
Keyword.put(config, :socket_options, [:inet6])
else
config
end

{:ok, config}
end

def transact(fun, opts \\ []) do
transaction(
fn ->
Expand Down
Loading