mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-01-16 17:38:17 +01:00
Refactor global variable script for clarity
Refactor script for better readability and maintainability. Update logging messages and streamline environment variable handling.
This commit is contained in:
@@ -3,429 +3,199 @@
|
||||
|
||||
set -e
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
################################################################################
|
||||
# Guard: only run inside Supervisor-managed add-ons
|
||||
# -----------------------------------------------------------------------------
|
||||
################################################################################
|
||||
if ! bashio::supervisor.ping 2>/dev/null; then
|
||||
echo "..."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo ""
|
||||
bashio::log.notice "This script converts add-on options (options.json) into environment variables."
|
||||
bashio::log.notice "Custom variables can be set using the env_vars option."
|
||||
bashio::log.notice "Additional informations : https://github.com/alexbelgium/hassio-addons/wiki/Add-Environment-variables-to-your-Addon-2"
|
||||
bashio::log.notice "Converting addon options to environment variables"
|
||||
bashio::log.notice "Supports custom env_vars"
|
||||
bashio::log.notice "https://github.com/alexbelgium/hassio-addons/wiki/Add-Environment-variables-to-your-Addon-2"
|
||||
echo ""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Inputs / outputs
|
||||
# -----------------------------------------------------------------------------
|
||||
################################################################################
|
||||
# Inputs
|
||||
################################################################################
|
||||
JSONSOURCE="/data/options.json"
|
||||
ENV_FILE="/.env"
|
||||
ETC_ENV_FILE="/etc/environment"
|
||||
|
||||
if [[ ! -f "$JSONSOURCE" ]]; then
|
||||
bashio::exit.nok "Missing ${JSONSOURCE}"
|
||||
fi
|
||||
|
||||
if ! command -v jq >/dev/null 2>&1; then
|
||||
bashio::exit.nok "jq is required but not found"
|
||||
fi
|
||||
[[ -f "$JSONSOURCE" ]] || bashio::exit.nok "Missing $JSONSOURCE"
|
||||
command -v jq >/dev/null || bashio::exit.nok "jq is required"
|
||||
|
||||
mkdir -p /etc
|
||||
touch "$ETC_ENV_FILE"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# mktemp helper (safe temp file creation)
|
||||
# -----------------------------------------------------------------------------
|
||||
################################################################################
|
||||
# Temp helper
|
||||
################################################################################
|
||||
mktemp_safe() {
|
||||
local tmpdir="${TMPDIR:-/tmp}"
|
||||
mkdir -p "$tmpdir" || return 1
|
||||
|
||||
local tmpfile
|
||||
tmpfile="$(mktemp "$tmpdir/tmp.XXXXXXXXXX")" || return 1
|
||||
printf '%s\n' "$tmpfile"
|
||||
mkdir -p "$tmpdir"
|
||||
mktemp "$tmpdir/tmp.XXXXXXXXXX"
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Secrets support:
|
||||
# - If an option value is "!secret foo", try to resolve it from secrets.yaml
|
||||
# -----------------------------------------------------------------------------
|
||||
################################################################################
|
||||
# Secrets support
|
||||
################################################################################
|
||||
SECRETSOURCE=""
|
||||
if [[ -f /homeassistant/secrets.yaml ]]; then
|
||||
SECRETSOURCE="/homeassistant/secrets.yaml"
|
||||
elif [[ -f /config/secrets.yaml ]]; then
|
||||
SECRETSOURCE="/config/secrets.yaml"
|
||||
fi
|
||||
[[ -f /homeassistant/secrets.yaml ]] && SECRETSOURCE="/homeassistant/secrets.yaml"
|
||||
[[ -z "$SECRETSOURCE" && -f /config/secrets.yaml ]] && SECRETSOURCE="/config/secrets.yaml"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Injection block markers:
|
||||
# 1) EXPORT_BLOCK_*: injected into run scripts / bashrc so services inherit vars
|
||||
# 2) FILE_BLOCK_* : written into /.env and /etc/environment (idempotent)
|
||||
# -----------------------------------------------------------------------------
|
||||
BLOCK_BEGIN="# --- BEGIN ADDON ENV (generated) ---"
|
||||
BLOCK_END="# --- END ADDON ENV (generated) ---"
|
||||
|
||||
FILE_BLOCK_BEGIN="# --- BEGIN ADDON ENV FILE (generated) ---"
|
||||
FILE_BLOCK_END="# --- END ADDON ENV FILE (generated) ---"
|
||||
|
||||
EXPORT_BLOCK_FILE="$(mktemp_safe)"
|
||||
ENV_KV_FILE="$(mktemp_safe)"
|
||||
trap 'rm -f "$EXPORT_BLOCK_FILE" "$ENV_KV_FILE"' EXIT
|
||||
|
||||
{
|
||||
echo "${BLOCK_BEGIN}"
|
||||
echo "# Do not edit: generated from ${JSONSOURCE}"
|
||||
echo "${BLOCK_END}"
|
||||
} > "${EXPORT_BLOCK_FILE}"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Protected variables that should not be overwritten
|
||||
# -----------------------------------------------------------------------------
|
||||
declare -A PROTECTED_VARS=(
|
||||
["PATH"]=1
|
||||
["HOME"]=1
|
||||
["PWD"]=1
|
||||
["SHLVL"]=1
|
||||
["_"]=1
|
||||
["S6_BEHAVIOR_IF_STAGE2_FAILS"]=1
|
||||
)
|
||||
|
||||
is_valid_env_name() {
|
||||
[[ "$1" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]
|
||||
resolve_secret() {
|
||||
local v="$1" name line
|
||||
[[ "$v" =~ ^[[:space:]]*\!secret[[:space:]]+(.+)$ ]] || { printf '%s' "$v"; return; }
|
||||
name="${BASH_REMATCH[1]}"
|
||||
[[ -n "$SECRETSOURCE" ]] || bashio::exit.nok "Secrets not mounted"
|
||||
line="$(awk -v k="$name" '$1==k":"{sub("^[^:]+:[[:space:]]*","");print;exit}' "$SECRETSOURCE")"
|
||||
[[ -n "$line" ]] || bashio::exit.nok "Secret $name not found"
|
||||
printf '%s' "$line"
|
||||
}
|
||||
|
||||
# Quote for shell *code* (for injection into scripts). Keep punctuation intact.
|
||||
# - single-line => single quotes
|
||||
# - multi-line => $'...\n...' (one physical line; safe for injection)
|
||||
shell_quote_for_code() {
|
||||
################################################################################
|
||||
# Quoting
|
||||
################################################################################
|
||||
dotenv_quote() {
|
||||
local v="$1"
|
||||
v="${v//\\/\\\\}"
|
||||
v="${v//\"/\\\"}"
|
||||
v="${v//$'\n'/\\n}"
|
||||
printf '"%s"' "$v"
|
||||
}
|
||||
|
||||
shell_quote() {
|
||||
local s="$1"
|
||||
|
||||
if [[ "$s" == *$'\n'* || "$s" == *$'\r'* || "$s" == *$'\t'* ]]; then
|
||||
s="${s//\\/\\\\}"
|
||||
s="${s//\'/\\\'}"
|
||||
s="${s//$'\n'/\\n}"
|
||||
s="${s//$'\r'/\\r}"
|
||||
s="${s//$'\t'/\\t}"
|
||||
printf "\$'%s'" "$s"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# single-quote with embedded '"'"' for literal '
|
||||
s="${s//\\/\\\\}"
|
||||
s="${s//\'/\'\"\'\"\' }"
|
||||
s="${s% }"
|
||||
printf "'%s'" "$s"
|
||||
}
|
||||
|
||||
dotenv_quote() {
|
||||
# For /.env and /etc/environment: double quotes + minimal escaping
|
||||
local v="$1"
|
||||
v="${v//\\/\\\\}"
|
||||
v="${v//\"/\\\"}"
|
||||
v="${v//$'\n'/\\n}"
|
||||
v="${v//$'\r'/\\r}"
|
||||
printf '"%s"' "$v"
|
||||
}
|
||||
################################################################################
|
||||
# S6 + script injection block
|
||||
################################################################################
|
||||
BLOCK_BEGIN="# --- BEGIN ADDON ENV (generated) ---"
|
||||
BLOCK_END="# --- END ADDON ENV (generated) ---"
|
||||
|
||||
resolve_secret_if_needed() {
|
||||
local v="$1"
|
||||
local name line
|
||||
|
||||
if [[ "$v" =~ ^[[:space:]]*\!secret[[:space:]]+(.+)[[:space:]]*$ ]]; then
|
||||
name="${BASH_REMATCH[1]}"
|
||||
name="${name#\"}"; name="${name%\"}"
|
||||
name="${name#\'}"; name="${name%\'}"
|
||||
|
||||
if [[ -z "${SECRETSOURCE}" ]]; then
|
||||
bashio::log.warning "Homeassistant config not mounted, secrets are not supported"
|
||||
printf '%s' "$v"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Exact key match at start of line; ignore comments
|
||||
line="$(
|
||||
awk -v k="$name" '
|
||||
/^[[:space:]]*#/ {next}
|
||||
$0 ~ "^[[:space:]]*" k ":[[:space:]]*" {
|
||||
sub("^[[:space:]]*" k ":[[:space:]]*", "", $0)
|
||||
print
|
||||
exit
|
||||
}
|
||||
' "$SECRETSOURCE"
|
||||
)"
|
||||
|
||||
[[ -z "$line" ]] && bashio::exit.nok "Secret '${name}' not found in ${SECRETSOURCE}"
|
||||
printf '%s' "$line"
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf '%s' "$v"
|
||||
}
|
||||
|
||||
append_export_line_for_injection() {
|
||||
# Insert one export line right before BLOCK_END in EXPORT_BLOCK_FILE.
|
||||
# (kept as-is to preserve behavior; safe and idempotent block replacement)
|
||||
local key="$1"
|
||||
local value="$2"
|
||||
local quoted
|
||||
quoted="$(shell_quote_for_code "$value")"
|
||||
|
||||
awk -v k="$key" -v q="$quoted" -v end="$BLOCK_END" '
|
||||
$0 == end { print "export " k "=" q }
|
||||
{ print }
|
||||
' "${EXPORT_BLOCK_FILE}" > "${EXPORT_BLOCK_FILE}.tmp"
|
||||
mv -f "${EXPORT_BLOCK_FILE}.tmp" "${EXPORT_BLOCK_FILE}"
|
||||
}
|
||||
|
||||
is_shell_run_script() {
|
||||
local f="$1"
|
||||
local h
|
||||
h="$(head -n 1 "$f" 2>/dev/null || true)"
|
||||
|
||||
[[ "$h" =~ ^#! ]] || return 1
|
||||
[[ "$h" =~ (sh|bash|with-contenv) ]] && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
inject_block_into_file() {
|
||||
# Inject/replace the generated export block in a target script:
|
||||
# - If the block exists: replace it.
|
||||
# - If not: insert it right after the shebang (if present), else at top.
|
||||
local file="$1"
|
||||
local tmp
|
||||
tmp="$(mktemp_safe)"
|
||||
|
||||
awk -v bfile="${EXPORT_BLOCK_FILE}" -v begin="${BLOCK_BEGIN}" -v end="${BLOCK_END}" '
|
||||
function print_block() {
|
||||
while ((getline l < bfile) > 0) print l
|
||||
close(bfile)
|
||||
}
|
||||
BEGIN { inblock=0; printed=0 }
|
||||
{
|
||||
if ($0 == begin) {
|
||||
inblock=1
|
||||
if (!printed) { print_block(); printed=1 }
|
||||
next
|
||||
}
|
||||
if ($0 == end) { inblock=0; next }
|
||||
if (inblock) next
|
||||
|
||||
if (NR == 1) {
|
||||
if ($0 ~ /^#!/) {
|
||||
print $0
|
||||
if (!printed) { print_block(); printed=1 }
|
||||
next
|
||||
} else {
|
||||
if (!printed) { print_block(); printed=1 }
|
||||
print $0
|
||||
next
|
||||
}
|
||||
}
|
||||
print $0
|
||||
}
|
||||
END {
|
||||
if (!printed) print_block()
|
||||
}
|
||||
' "$file" > "$tmp"
|
||||
|
||||
cat "$tmp" > "$file"
|
||||
rm -f "$tmp"
|
||||
}
|
||||
|
||||
update_scripts_with_block() {
|
||||
# Inject the export block into common service scripts and entrypoints.
|
||||
local f
|
||||
local -A seen=()
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
# Includes legacy and newer s6 locations
|
||||
for f in /etc/services.d/*/run /etc/services.d/*/*run* /etc/cont-init.d/*.sh /etc/s6-overlay/s6-rc.d/*/run /*/entrypoint.sh /entrypoint.sh; do
|
||||
[[ -f "$f" ]] || continue
|
||||
[[ -n "${seen[$f]:-}" ]] && continue
|
||||
seen["$f"]=1
|
||||
|
||||
if ! is_shell_run_script "$f"; then
|
||||
bashio::log.debug "Skipping non-shell script: $f"
|
||||
continue
|
||||
fi
|
||||
|
||||
inject_block_into_file "$f"
|
||||
done
|
||||
|
||||
shopt -u nullglob
|
||||
}
|
||||
|
||||
replace_block_in_file() {
|
||||
# Replace (or add) a generated block inside a plain text file.
|
||||
# Used for /.env and /etc/environment to prevent infinite append growth.
|
||||
local file="$1"
|
||||
local begin="$2"
|
||||
local end="$3"
|
||||
local content_file="$4"
|
||||
local tmp
|
||||
|
||||
tmp="$(mktemp_safe)"
|
||||
|
||||
if [[ ! -f "$file" ]]; then
|
||||
touch "$file"
|
||||
fi
|
||||
|
||||
awk -v bfile="$content_file" -v begin="$begin" -v end="$end" '
|
||||
function print_block() {
|
||||
while ((getline l < bfile) > 0) print l
|
||||
close(bfile)
|
||||
}
|
||||
BEGIN { inblock=0; printed=0 }
|
||||
{
|
||||
if ($0 == begin) {
|
||||
inblock=1
|
||||
if (!printed) { print_block(); printed=1 }
|
||||
next
|
||||
}
|
||||
if ($0 == end) { inblock=0; next }
|
||||
if (inblock) next
|
||||
print $0
|
||||
}
|
||||
END { if (!printed) print_block() }
|
||||
' "$file" > "$tmp"
|
||||
|
||||
cat "$tmp" > "$file"
|
||||
rm -f "$tmp"
|
||||
}
|
||||
|
||||
export_option() {
|
||||
# Core exporter:
|
||||
# - validates key
|
||||
# - resolves secrets
|
||||
# - logs (redacted if sensitive unless verbose)
|
||||
# - exports into current process
|
||||
# - exports into s6 environment
|
||||
# - queues key/value for generated /.env and /etc/environment blocks
|
||||
# - adds export into injection block for scripts
|
||||
local key="$1"
|
||||
local value="$2"
|
||||
|
||||
if [[ -n "${PROTECTED_VARS[$key]:-}" ]]; then
|
||||
bashio::log.warning "Skipping protected environment variable: ${key}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! is_valid_env_name "$key"; then
|
||||
bashio::log.warning "Skipping invalid env var name: ${key}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
value="$(resolve_secret_if_needed "$value")"
|
||||
|
||||
if bashio::config.false "verbose" || [[ "${key,,}" =~ (pass|secret|token|apikey|api_key|private|pwd) ]]; then
|
||||
bashio::log.blue "${key}=******"
|
||||
else
|
||||
bashio::log.blue "${key}=${value}"
|
||||
fi
|
||||
|
||||
export "${key}=${value}"
|
||||
|
||||
# Export for s6 services (preferred way)
|
||||
if [[ -d /var/run/s6/container_environment ]]; then
|
||||
printf '%s' "${value}" > "/var/run/s6/container_environment/${key}"
|
||||
fi
|
||||
|
||||
# Queue dotenv-style line for writing once (idempotent file update later)
|
||||
echo "${key}=$(dotenv_quote "$value")" >> "$ENV_KV_FILE" 2>/dev/null || true
|
||||
|
||||
# Ensure scripts/services also see it (block injection)
|
||||
append_export_line_for_injection "$key" "$value"
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# One jq pass emits normalized key/value pairs:
|
||||
# - exports all scalar top-level options (strings/numbers/bools)
|
||||
# - skips objects/arrays (except env_vars)
|
||||
# - supports env_vars formats:
|
||||
# 1) [{name:"FOO", value:"bar"}, ...]
|
||||
# 2) [{FOO:"bar", BAZ:"qux"}, ...]
|
||||
# 3) ["FOO=bar", ...] (value may contain '=')
|
||||
# -----------------------------------------------------------------------------
|
||||
while IFS= read -r -d $'\0' key && IFS= read -r value; do
|
||||
export_option "$key" "$value"
|
||||
done < <(
|
||||
jq -r '
|
||||
def emit(k; v): "\((k|tostring))\u0000\((v|tostring))";
|
||||
|
||||
# --- 1) env_vars[] ---
|
||||
( .env_vars? // [] )[] as $ev
|
||||
| if ($ev | type) == "object" then
|
||||
if ($ev | has("name") and has("value")) then
|
||||
emit($ev.name; ($ev.value // ""))
|
||||
else
|
||||
($ev | to_entries[] | emit(.key; (.value // "")))
|
||||
end
|
||||
else
|
||||
($ev | tostring) as $s
|
||||
| if ($s | test("^[^=]+=")) then
|
||||
($s | capture("^(?<k>[^=]+)=(?<v>.*)$")) as $m
|
||||
| emit($m.k; $m.v)
|
||||
else empty end
|
||||
end
|
||||
,
|
||||
# --- 2) top-level scalars excluding env_vars ---
|
||||
to_entries[]
|
||||
| select(.key != "env_vars")
|
||||
| select((.value|type) != "array" and (.value|type) != "object" and (.value|type) != "null")
|
||||
| emit(.key; .value)
|
||||
' "$JSONSOURCE"
|
||||
)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Write /.env and /etc/environment in an idempotent way (no infinite appends)
|
||||
# -----------------------------------------------------------------------------
|
||||
# Ensure /.env has a header (only if missing)
|
||||
if [[ ! -f "$ENV_FILE" ]]; then
|
||||
printf '# Generated by 00-global_var.sh from %s\n' "$JSONSOURCE" > "$ENV_FILE"
|
||||
fi
|
||||
|
||||
ENV_FILE_BLOCK="$(mktemp_safe)"
|
||||
trap 'rm -f "$EXPORT_BLOCK_FILE" "$ENV_KV_FILE" "$ENV_FILE_BLOCK"' EXIT
|
||||
EXPORT_BLOCK="$(mktemp_safe)"
|
||||
KV_FILE="$(mktemp_safe)"
|
||||
trap 'rm -f "$EXPORT_BLOCK" "$KV_FILE"' EXIT
|
||||
|
||||
{
|
||||
echo "${FILE_BLOCK_BEGIN}"
|
||||
echo "# Do not edit: generated from ${JSONSOURCE}"
|
||||
cat "$ENV_KV_FILE" 2>/dev/null || true
|
||||
echo "${FILE_BLOCK_END}"
|
||||
} > "$ENV_FILE_BLOCK"
|
||||
echo "$BLOCK_BEGIN"
|
||||
echo "# Generated from $JSONSOURCE"
|
||||
echo "$BLOCK_END"
|
||||
} > "$EXPORT_BLOCK"
|
||||
|
||||
replace_block_in_file "$ENV_FILE" "$FILE_BLOCK_BEGIN" "$FILE_BLOCK_END" "$ENV_FILE_BLOCK"
|
||||
replace_block_in_file "$ETC_ENV_FILE" "$FILE_BLOCK_BEGIN" "$FILE_BLOCK_END" "$ENV_FILE_BLOCK"
|
||||
append_export() {
|
||||
local k="$1" v="$2"
|
||||
local q
|
||||
q="$(shell_quote "$v")"
|
||||
awk -v k="$k" -v q="$q" -v e="$BLOCK_END" '$0==e{print "export "k"="q}1' "$EXPORT_BLOCK" > "$EXPORT_BLOCK.tmp"
|
||||
mv "$EXPORT_BLOCK.tmp" "$EXPORT_BLOCK"
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Inject generated export block into service scripts and interactive shells
|
||||
# -----------------------------------------------------------------------------
|
||||
update_scripts_with_block
|
||||
inject_block() {
|
||||
local f="$1" tmp
|
||||
tmp="$(mktemp_safe)"
|
||||
awk -v b="$BLOCK_BEGIN" -v e="$BLOCK_END" -v bf="$EXPORT_BLOCK" '
|
||||
function emit(){while((getline l<bf)>0)print l;close(bf)}
|
||||
BEGIN{p=0}
|
||||
{
|
||||
if($0==b){skip=1;emit();next}
|
||||
if($0==e){skip=0;next}
|
||||
if(skip)next
|
||||
if(NR==1 && $0~/^#!/){print;emit();next}
|
||||
print
|
||||
}
|
||||
END{if(!skip)emit()}
|
||||
' "$f" > "$tmp"
|
||||
cat "$tmp" > "$f"
|
||||
rm -f "$tmp"
|
||||
}
|
||||
|
||||
# System-wide interactive bash shells
|
||||
touch "/etc/bash.bashrc"
|
||||
inject_block_into_file "/etc/bash.bashrc"
|
||||
################################################################################
|
||||
# Export handler
|
||||
################################################################################
|
||||
export_var() {
|
||||
local k="$1" v="$2"
|
||||
|
||||
# Common per-user interactive bash shell config (more standard than bash.bashrc)
|
||||
if [[ -n "${HOME:-}" ]]; then
|
||||
mkdir -p "$HOME"
|
||||
touch "$HOME/.bashrc"
|
||||
inject_block_into_file "$HOME/.bashrc"
|
||||
[[ "$k" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] || return
|
||||
|
||||
# Kept for compatibility with images that use this non-standard name
|
||||
touch "$HOME/bash.bashrc"
|
||||
inject_block_into_file "$HOME/bash.bashrc"
|
||||
fi
|
||||
v="$(resolve_secret "$v")"
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Set timezone (kept identical in behavior)
|
||||
# -----------------------------------------------------------------------------
|
||||
set +eu
|
||||
|
||||
if [ -n "$TZ" ] && [ -f /etc/localtime ]; then
|
||||
if [ -f /usr/share/zoneinfo/"$TZ" ]; then
|
||||
echo "Timezone set from $(cat /etc/timezone) to $TZ"
|
||||
ln -snf /usr/share/zoneinfo/"$TZ" /etc/localtime && echo "$TZ" > /etc/timezone
|
||||
if [[ "${k,,}" =~ pass|token|secret|key ]]; then
|
||||
bashio::log.blue "$k=******"
|
||||
else
|
||||
bashio::log.blue "$k=$v"
|
||||
fi
|
||||
|
||||
export "$k=$v"
|
||||
|
||||
[[ -d /var/run/s6/container_environment ]] && printf '%s' "$v" > "/var/run/s6/container_environment/$k"
|
||||
|
||||
echo "$k=$(dotenv_quote "$v")" >> "$KV_FILE"
|
||||
append_export "$k" "$v"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# JSON parsing (safe + jq bug fixed)
|
||||
################################################################################
|
||||
while IFS= read -r -d $'\0' k && IFS= read -r v; do
|
||||
export_var "$k" "$v"
|
||||
done < <(
|
||||
jq -r '
|
||||
def emit(k;v): "\((k|tostring))\u0000\((v|tostring))";
|
||||
. as $root
|
||||
|
|
||||
(
|
||||
($root.env_vars?//[])[]? as $e
|
||||
| if $e|type=="object" then
|
||||
if $e|has("name") and has("value") then emit($e.name;$e.value)
|
||||
else $e|to_entries[]|emit(.key;.value) end
|
||||
else
|
||||
($e|tostring) as $s
|
||||
| if $s|test("=") then
|
||||
($s|capture("^(?<k>[^=]+)=(?<v>.*)$"))|emit(.k;.v)
|
||||
else empty end
|
||||
end
|
||||
),
|
||||
(
|
||||
$root|to_entries[]
|
||||
| select(.key!="env_vars")
|
||||
| select((.value|type)!="object" and (.value|type)!="array")
|
||||
| emit(.key;.value)
|
||||
)
|
||||
' "$JSONSOURCE"
|
||||
)
|
||||
|
||||
################################################################################
|
||||
# Write .env and /etc/environment (idempotent)
|
||||
################################################################################
|
||||
{
|
||||
echo "$BLOCK_BEGIN"
|
||||
cat "$KV_FILE"
|
||||
echo "$BLOCK_END"
|
||||
} > "$ENV_FILE.tmp"
|
||||
mv "$ENV_FILE.tmp" "$ENV_FILE"
|
||||
cp "$ENV_FILE" "$ETC_ENV_FILE"
|
||||
|
||||
################################################################################
|
||||
# Inject into scripts and shells
|
||||
################################################################################
|
||||
for f in /etc/services.d/*/run /etc/cont-init.d/*.sh /entrypoint.sh /etc/bash.bashrc "$HOME/.bashrc"; do
|
||||
[[ -f "$f" ]] && inject_block "$f"
|
||||
done
|
||||
|
||||
################################################################################
|
||||
# Timezone
|
||||
################################################################################
|
||||
set +e
|
||||
if [[ -n "$TZ" && -f "/usr/share/zoneinfo/$TZ" ]]; then
|
||||
ln -snf "/usr/share/zoneinfo/$TZ" /etc/localtime
|
||||
echo "$TZ" > /etc/timezone
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user