Skip to content
This repository has been archived by the owner on Jun 30, 2021. It is now read-only.

Commit

Permalink
Switch to use DeferredConfig (#343)
Browse files Browse the repository at this point in the history
  • Loading branch information
sirn authored Jul 24, 2018
1 parent 6ac1c00 commit c8f9d3f
Show file tree
Hide file tree
Showing 42 changed files with 232 additions and 181 deletions.
48 changes: 4 additions & 44 deletions apps/admin_api/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ use Mix.Config
config :admin_api,
namespace: AdminAPI,
ecto_repos: [],
base_url: System.get_env("BASE_URL") || "http://localhost:4000",
sender_email: System.get_env("SENDER_EMAIL") || "admin@localhost"
base_url: {:system, "BASE_URL", "http://localhost:4000"},
sender_email: {:system, "SENDER_EMAIL", "admin@localhost"}

# Configs for the endpoint
config :admin_api, AdminAPI.Endpoint,
secret_key_base: System.get_env("SECRET_KEY_BASE"),
secret_key_base: {:system, "SECRET_KEY_BASE"},
error_handler: AdminAPI.V1.ErrorHandler,
render_errors: [
view: AdminAPI.ErrorView,
Expand All @@ -39,46 +39,6 @@ config :admin_api, :generators, context_app: false
# Configs for Bamboo emailing library
config :admin_api, AdminAPI.Mailer, adapter: Bamboo.LocalAdapter

# Config for CORSPlug
#
# CORS_ORIGINS may contain multiple comma-separated origins, therefore it needs
# to be splitted and trimmed. But since `config.exs` evaluates the options
# at compile time, it does not allow an assignment with anonymous functions,
# waiting to be executed at runtime.
#
# Because of this the anonymous function is invoked right away through
# `(fn -> ... end).()` in order for :origin to be assigned at compile time.
config :cors_plug,
# Lowest common value of all browsers
max_age: System.get_env("CORS_MAX_AGE") || 600,
headers: [
"Authorization",
"Content-Type",
"Accept",
"Origin",
"User-Agent",
"DNT",
"Cache-Control",
"X-Mx-ReqToken",
"Keep-Alive",
"X-Requested-With",
"If-Modified-Since",
"X-CSRF-Token",
"OMGAdmin-Account-ID"
],
methods: ["POST"],
origin:
(fn ->
case System.get_env("CORS_ORIGINS") do
# Disallow all origins if CORS_ORIGINS is not set
nil ->
[]

origins ->
origins |> String.trim() |> String.split(~r{\s*,\s*})
end
end).()

# Two configs need to be added to have a new EWallet Admin version:
#
# 1. `admin_api.api_versions`
Expand All @@ -104,7 +64,7 @@ config :mime, :types, %{

# Configs for Sentry exception reporting
config :sentry,
dsn: System.get_env("SENTRY_DSN"),
dsn: {:system, "SENTRY_DSN"},
environment_name: Mix.env(),
enable_source_code_context: true,
root_source_code_path: File.cwd!(),
Expand Down
10 changes: 5 additions & 5 deletions apps/admin_api/config/prod.exs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use Mix.Config

config :admin_panel, base_url: System.get_env("BASE_URL")
config :admin_panel, base_url: {:system, "BASE_URL"}

# Configs for Bamboo emailing library
config :admin_api, AdminAPI.Mailer,
adapter: Bamboo.SMTPAdapter,
server: System.get_env("SMTP_HOST"),
port: System.get_env("SMTP_PORT"),
username: System.get_env("SMTP_USER"),
password: System.get_env("SMTP_PASSWORD")
server: {:system, "SMTP_HOST"},
port: {:system, "SMTP_PORT"},
username: {:system, "SMTP_USER"},
password: {:system, "SMTP_PASSWORD"}

config :admin_api, AdminAPI.V1.Endpoint,
debug_errors: true,
Expand Down
3 changes: 3 additions & 0 deletions apps/admin_api/lib/admin_api/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ defmodule AdminAPI.Application do
"""
use Application
alias AdminAPI.Endpoint
alias AdminAPI.Config

def start(_type, _args) do
import Supervisor.Spec
DeferredConfig.populate(:admin_api)
Config.configure_cors_plug()

# Define workers and child supervisors to be supervised
children = [
Expand Down
39 changes: 39 additions & 0 deletions apps/admin_api/lib/admin_api/config.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
defmodule AdminAPI.Config do
@moduledoc """
Provides a configuration function that are called during application startup.
"""

@headers [
"Authorization",
"Content-Type",
"Accept",
"Origin",
"User-Agent",
"DNT",
"Cache-Control",
"X-Mx-ReqToken",
"Keep-Alive",
"X-Requested-With",
"If-Modified-Since",
"X-CSRF-Token",
"OMGAdmin-Account-ID"
]

def configure_cors_plug do
max_age = System.get_env("CORS_MAX_AGE") || 600
cors_origin = System.get_env("CORS_ORIGIN")

Application.put_env(:cors_plug, :max_age, max_age)
Application.put_env(:cors_plug, :headers, @headers)
Application.put_env(:cors_plug, :methods, ["POST"])
Application.put_env(:cors_plug, :origin, cors_plug_origin(cors_origin))
end

defp cors_plug_origin(nil), do: []

defp cors_plug_origin(origins) do
origins
|> String.trim()
|> String.split(~r{\s*,\s*})
end
end
2 changes: 1 addition & 1 deletion apps/admin_api/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ defmodule AdminAPI.Mixfile do
{:phoenix, "~> 1.3.0"},
{:cowboy, "~> 1.0"},
{:cors_plug, "~> 1.5"},
{:sentry, "~> 6.0.0"},
{:sentry, "~> 6.2.0"},
{:bamboo, "~> 0.8"},
{:bamboo_smtp, "~> 1.4.0"},
{:bodyguard, "~> 2.2"},
Expand Down
2 changes: 1 addition & 1 deletion apps/ewallet/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ use Mix.Config

config :ewallet,
ecto_repos: [],
max_per_page: System.get_env("REQUEST_MAX_PER_PAGE") || 100
max_per_page: {:system, "REQUEST_MAX_PER_PAGE"}

import_config "#{Mix.env()}.exs"
15 changes: 14 additions & 1 deletion apps/ewallet/lib/ewallet/web/paginator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,20 @@ defmodule EWallet.Web.Paginator do
# Returns the per_page number or default, but never greater than the system's defined limit
defp get_per_page(attrs) do
per_page = Map.get(attrs, "per_page", @default_per_page)
max_per_page = Application.get_env(:ewallet, :max_per_page, @default_max_per_page)

max_per_page =
case Application.get_env(:ewallet, :max_per_page, @default_max_per_page) do
{:system, env_var} ->
case System.get_env(env_var) do
"" -> @default_max_per_page
nil -> @default_max_per_page
value when is_binary(value) -> String.to_integer(value)
value -> value
end

value ->
value
end

case per_page do
n when n > max_per_page -> max_per_page
Expand Down
11 changes: 11 additions & 0 deletions apps/ewallet/test/ewallet/web/paginator_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ defmodule EWallet.Web.PaginatorTest do
Application.delete_env(:ewallet, :max_per_page)
end

test "returns per_page if max_per_page is configured as a system tuple" do
System.put_env("_TMP_MAX_PER_PAGE", "20")
Application.put_env(:ewallet, :max_per_page, {:system, "_TMP_MAX_PER_PAGE"})

paginator = Paginator.paginate_attrs(Account, %{"per_page" => 100})
assert paginator.pagination.per_page == 20

Application.delete_env(:ewallet, :max_per_page)
System.delete_env("_TMP_MAX_PER_PAGE")
end

test "returns :error if given attrs.page is a negative integer" do
result = Paginator.paginate_attrs(Account, %{"page" => -1})
assert {:error, :invalid_parameter, _} = result
Expand Down
2 changes: 1 addition & 1 deletion apps/ewallet_api/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ config :mime, :types, %{

# Configs for Sentry exception reporting
config :sentry,
dsn: System.get_env("SENTRY_DSN"),
dsn: {:system, "SENTRY_DSN"},
environment_name: Mix.env(),
enable_source_code_context: true,
root_source_code_path: File.cwd!(),
Expand Down
4 changes: 2 additions & 2 deletions apps/ewallet_api/config/prod.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ config :ewallet_api, EWalletAPI.V1.Endpoint,
# Config for node discovery.
config :peerage,
via: Peerage.Via.Dns,
dns_name: System.get_env("NODE_DNS") || "localhost",
app_name: System.get_env("NODE_NAME") || "ewallet"
dns_name: {:system, "NODE_DNS", "localhost"},
app_name: {:system, "NODE_NAME", "ewallet"}

# For production, we often load configuration from external
# sources, such as your system environment. For this reason,
Expand Down
2 changes: 1 addition & 1 deletion apps/ewallet_api/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ defmodule EWalletAPI.Mixfile do
[
{:phoenix, "~> 1.3.0"},
{:cowboy, "~> 1.0"},
{:sentry, "~> 6.0.0"},
{:sentry, "~> 6.2.0"},
{:peerage, "~> 1.0.2"},
{:ewallet_db, in_umbrella: true},
{:ewallet, in_umbrella: true}
Expand Down
30 changes: 0 additions & 30 deletions apps/ewallet_db/config/adapters/aws.exs

This file was deleted.

12 changes: 0 additions & 12 deletions apps/ewallet_db/config/adapters/gcs.exs

This file was deleted.

3 changes: 0 additions & 3 deletions apps/ewallet_db/config/adapters/local.exs

This file was deleted.

10 changes: 1 addition & 9 deletions apps/ewallet_db/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,7 @@ use Mix.Config
config :ewallet_db,
ecto_repos: [EWalletDB.Repo],
env: Mix.env(),
base_url: System.get_env("BASE_URL") || "http://localhost:4000",
base_url: {:system, "BASE_URL", "http://localhost:4000"},
min_password_length: 8

import_config "#{Mix.env()}.exs"

storage_adapter = System.get_env("FILE_STORAGE_ADAPTER") || "local"

case storage_adapter do
"aws" -> import_config "adapters/aws.exs"
"gcs" -> import_config "adapters/gcs.exs"
"local" -> import_config "adapters/local.exs"
end
2 changes: 1 addition & 1 deletion apps/ewallet_db/config/dev.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ use Mix.Config

config :ewallet_db, EWalletDB.Repo,
adapter: Ecto.Adapters.Postgres,
url: System.get_env("DATABASE_URL") || "postgres://localhost/ewallet_dev"
url: {:system, "DATABASE_URL", "postgres://localhost/ewallet_dev"}
4 changes: 2 additions & 2 deletions apps/ewallet_db/config/prod.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ use Mix.Config

config :ewallet_db, EWalletDB.Repo,
adapter: Ecto.Adapters.Postgres,
url: System.get_env("DATABASE_URL") || "postgres://localhost/ewallet_prod"
url: {:system, "DATABASE_URL", "postgres://localhost/ewallet_prod"}

config :ewallet_db, base_url: System.get_env("BASE_URL")
config :ewallet_db, base_url: {:system, "BASE_URL"}
2 changes: 1 addition & 1 deletion apps/ewallet_db/config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ use Mix.Config
config :ewallet_db, EWalletDB.Repo,
adapter: Ecto.Adapters.Postgres,
pool: Ecto.Adapters.SQL.Sandbox,
url: System.get_env("DATABASE_URL") || "postgres://localhost/ewallet_test"
url: {:system, "DATABASE_URL", "postgres://localhost/ewallet_test"}
3 changes: 3 additions & 0 deletions apps/ewallet_db/lib/ewallet_db/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ defmodule EWalletDB.Application do
Kebura's data store lives in this application.
"""
use Application
alias EWalletDB.Config

def start(_type, _args) do
import Supervisor.Spec
DeferredConfig.populate(:ewallet_db)
Config.configure_file_storage()

# List all child processes to be supervised
children = [
Expand Down
43 changes: 43 additions & 0 deletions apps/ewallet_db/lib/ewallet_db/config.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
defmodule EWalletDB.Config do
@moduledoc """
Provides a configuration function that are called during application startup.
"""

def configure_file_storage do
storage_adapter = System.get_env("FILE_STORAGE_ADAPTER") || "local"
configure_file_storage(storage_adapter)
end

defp configure_file_storage("aws") do
aws_bucket = System.get_env("AWS_BUCKET")
aws_region = System.get_env("AWS_REGION")
aws_access_key_id = System.get_env("AWS_ACCESS_KEY_ID")
aws_secret_access_key = System.get_env("AWS_SECRET_ACCESS_KEY")

aws_domain = "s3-#{aws_region}.amazonaws.com"

Application.put_env(:ex_aws, :access_key_id, [aws_access_key_id, :instance_role])
Application.put_env(:ex_aws, :secret_access_key, [aws_secret_access_key, :instance_role])
Application.put_env(:ex_aws, :region, aws_region)
Application.put_env(:ex_aws, :s3, scheme: "https://", host: aws_domain, region: aws_region)
Application.put_env(:ex_aws, :debug_requests, true)
Application.put_env(:ex_aws, :recv_timeout, 60_000)
Application.put_env(:ex_aws, :hackney, recv_timeout: 60_000, pool: false)
Application.put_env(:arc, :storage, Arc.Storage.S3)
Application.put_env(:arc, :bucket, aws_bucket)
Application.put_env(:arc, :asset_host, "https://#{aws_domain}/#{aws_bucket}")
end

defp configure_file_storage("gcs") do
gcs_bucket = System.get_env("GCS_BUCKET")
gcs_credentials = System.get_env("GCS_CREDENTIALS")

Application.put_env(:arc, :storage, Arc.Storage.GCS)
Application.put_env(:arc, :bucket, gcs_bucket)
Application.put_env(:goth, :json, gcs_credentials)
end

defp configure_file_storage("local") do
Application.put_env(:arc, :storage, EWallet.Storage.Local)
end
end
14 changes: 14 additions & 0 deletions apps/ewallet_db/lib/ewallet_db/repo.ex
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
defmodule EWalletDB.Repo do
use Ecto.Repo, otp_app: :ewallet_db

# Workaround an issue where ecto.migrate task won't start the app
# thus DeferredConfig.populate is not getting called.
#
# Ecto itself only supports {:system, ENV_VAR} tuple, but not
# DeferredConfig's {:system, ENV_VAR, DEFAULT} tuple nor the
# {:apply, MFA} tuple.
#
# See also: https://github.com/mrluc/deferred_config/issues/2
def init(_, config) do
config
|> DeferredConfig.transform_cfg()
|> (fn updated -> {:ok, updated} end).()
end
end
Loading

0 comments on commit c8f9d3f

Please sign in to comment.