Packages
testcontainers
2.2.0
2.3.1
2.3.0
2.2.0
2.1.0
2.1.0-rc1
2.0.0
2.0.0-rc3
2.0.0-rc2
2.0.0-rc
1.14.1
1.14.0
1.13.5
1.13.4
1.13.3
1.13.2
1.13.1
1.13.0
1.12.0
1.11.8
1.11.7
1.11.6
1.11.5
1.11.4
1.11.3
1.11.2
1.11.1
1.11.0
1.10.5
1.10.4
1.10.3
1.10.2
1.10.1
1.10.0
1.9.0
1.8.4
1.8.3
1.8.2
1.8.1
1.8.0
1.7.0
1.6.0
1.5.1
1.5.0
1.4.2
1.4.1
1.4.0
1.3.1
1.3.0
1.2.11
1.2.10
1.2.9
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.3
1.1.2
1.1.1
1.1.0
1.0.1
1.0.0
1.0.0-beta.1
1.0.0-beta
0.9.3
0.9.2
0.9.1
0.9.0
Testcontainers is an Elixir library that supports ExUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.
Current section
Files
Jump to
Current section
Files
lib/util/properties.ex
defmodule Testcontainers.Util.PropertiesParser do
@moduledoc false
@user_file "~/.testcontainers.properties"
@project_file ".testcontainers.properties"
@env_prefix "TESTCONTAINERS_"
def read_property_file(file_path \\ @user_file) do
if File.exists?(Path.expand(file_path)) do
with {:ok, content} <- File.read(Path.expand(file_path)),
properties <- parse_properties(content) do
{:ok, properties}
else
error ->
{:error, properties: error}
end
else
# return empty map if file does not exist
{:ok, %{}}
end
end
@doc """
Reads properties from all sources with proper precedence.
Configuration is read from three sources with the following precedence
(highest to lowest):
1. Environment variables (TESTCONTAINERS_* prefix)
2. User file (~/.testcontainers.properties)
3. Project file (.testcontainers.properties)
Environment variables are converted from TESTCONTAINERS_PROPERTY_NAME format
to property.name format (uppercase to lowercase, underscores to dots, prefix removed).
## Options
- `:user_file` - path to user properties file (default: ~/.testcontainers.properties)
- `:project_file` - path to project properties file (default: .testcontainers.properties)
- `:env_prefix` - environment variable prefix (default: TESTCONTAINERS_)
## Returns
- `{:ok, map}` with merged properties.
"""
def read_property_sources(opts \\ []) do
user_file = Keyword.get(opts, :user_file, @user_file)
project_file = Keyword.get(opts, :project_file, @project_file)
env_prefix = Keyword.get(opts, :env_prefix, @env_prefix)
project_props = read_file_silent(project_file)
user_props = read_file_silent(user_file)
env_props = read_env_vars(env_prefix)
# Merge in order of lowest to highest precedence
merged =
project_props
|> Map.merge(user_props)
|> Map.merge(env_props)
{:ok, merged}
end
defp read_file_silent(file_path) do
expanded = Path.expand(file_path)
if File.exists?(expanded) do
case File.read(expanded) do
{:ok, content} -> parse_properties(content)
{:error, _} -> %{}
end
else
%{}
end
end
defp read_env_vars(prefix) do
System.get_env()
|> Enum.filter(fn {key, _value} -> String.starts_with?(key, prefix) end)
|> Enum.map(&env_to_property(&1, prefix))
|> Map.new()
end
# Converts TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED to ryuk.container.privileged
defp env_to_property({key, value}, prefix) do
property_key =
key
|> String.replace_prefix(prefix, "")
|> String.downcase()
|> String.replace("_", ".")
{property_key, value}
end
defp parse_properties(content) do
content
|> String.split("\n")
|> Enum.map(&String.trim/1)
|> Enum.reject(&(&1 == "" or String.starts_with?(&1, "#")))
|> Enum.flat_map(&extract_key_value_pair/1)
|> Enum.into(%{})
end
defp extract_key_value_pair(line) do
case String.split(line, "=", parts: 2) do
[key, value] when is_binary(value) ->
[{String.trim(key), String.trim(value)}]
_other ->
[]
end
end
end