1
0

Compare commits

..

2 Commits

Author SHA1 Message Date
d4024d5d5f
image entrypoint improvements 2024-07-26 01:18:59 +03:00
48de90954f
j2cfg code improvements 2024-07-25 11:11:44 +03:00
12 changed files with 157 additions and 176 deletions

View File

@ -47,7 +47,6 @@ log_always() {
log() { log() {
[ "${IEP_VERBOSE}" = 0 ] || log_always "$@" [ "${IEP_VERBOSE}" = 0 ] || log_always "$@"
} }
log_file() { sed -E '/^./s,^, ,' < "$1" >&2 ; }
ln_s() { ln_s() {
if [ "${IEP_VERBOSE}" = 0 ] ; then if [ "${IEP_VERBOSE}" = 0 ] ; then
@ -76,39 +75,6 @@ have_cmd() { command -v "$1" >/dev/null 2>&1 || return ; }
strip_suffix() { printf '%s' "${1%"$2"}" | tr -s '/' ; } strip_suffix() { printf '%s' "${1%"$2"}" | tr -s '/' ; }
untemplate_path() {
case "$1" in
## inplace
"${volume_root}"/* | /etc/angie/run/* )
strip_suffix "$1" "$2"
;;
/etc/angie/autoconf.d/* | /etc/angie/conf.d/* | /etc/angie/j2cfg.d/* | /etc/angie/mod.d/* | /etc/angie/modules.d/* | /etc/angie/site.d/* | /etc/angie/snip.d/* )
strip_suffix "$1" "$2"
;;
/etc/angie/static.d/* )
strip_suffix "$1" "$2"
;;
## set appropriate location
/etc/angie/* )
strip_suffix "${volume_root}${1#/etc/angie}" "$2"
;;
/tmp/* )
log_always "untemplate_path() shouldn't work with /tmp/: $1"
strip_suffix "$1" "$2"
;;
## last resort - STRONGLY AVOID
/* )
log_always "untemplate_path() does uncommon/last-resort mapping for: $1"
strip_suffix "${tmp_dir}$1" "$2"
;;
## misbehavior!
* )
log_always "untemplate_path() doesn't work with relative paths: $1"
return 1
;;
esac
}
install_userdir() { install_userdir() {
if [ "${IEP_ROOT}" = 1 ] ; then if [ "${IEP_ROOT}" = 1 ] ; then
install -d -o "${NGX_USER}" -g "${NGX_GROUP}" "$@" install -d -o "${NGX_USER}" -g "${NGX_GROUP}" "$@"
@ -208,69 +174,6 @@ expand_dir_j2cfg() {
return ${__ret} return ${__ret}
} }
remap_path() {
[ -n "$1" ] || return
case "$1" in
## autoconf
/etc/angie/autoconf.dist/* ) echo "${2:-/etc/angie/autoconf.d}${1#/etc/angie/autoconf.dist}" ;;
/etc/angie/autoconf/* ) echo "${2:-/etc/angie/autoconf.d}${1#/etc/angie/autoconf}" ;;
/angie/autoconf/* ) echo "${2:-/etc/angie/autoconf.d}${1#/angie/autoconf}" ;;
## conf
/etc/angie/conf.dist/* ) echo "${2:-/etc/angie/conf.d}${1#/etc/angie/conf.dist}" ;;
/etc/angie/conf/* ) echo "${2:-/etc/angie/conf.d}${1#/etc/angie/conf}" ;;
/angie/conf/* ) echo "${2:-/etc/angie/conf.d}${1#/angie/conf}" ;;
## j2cfg
/etc/angie/j2cfg.dist/* ) echo "${2:-/etc/angie/j2cfg.d}${1#/etc/angie/j2cfg.dist}" ;;
/etc/angie/j2cfg/* ) echo "${2:-/etc/angie/j2cfg.d}${1#/etc/angie/j2cfg}" ;;
/angie/j2cfg/* ) echo "${2:-/etc/angie/j2cfg.d}${1#/angie/j2cfg}" ;;
## mod
/etc/angie/mod.dist/* ) echo "${2:-/etc/angie/mod.d}${1#/etc/angie/mod.dist}" ;;
/etc/angie/mod/* ) echo "${2:-/etc/angie/mod.d}${1#/etc/angie/mod}" ;;
/angie/mod/* ) echo "${2:-/etc/angie/mod.d}${1#/angie/mod}" ;;
## modules
/etc/angie/modules.dist/* ) echo "${2:-/etc/angie/modules.d}${1#/etc/angie/modules.dist}" ;;
/etc/angie/modules/* ) echo "${2:-/etc/angie/modules.d}${1#/etc/angie/modules}" ;;
/angie/modules/* ) echo "${2:-/etc/angie/modules.d}${1#/angie/modules}" ;;
## site
/etc/angie/site.dist/* ) echo "${2:-/etc/angie/site.d}${1#/etc/angie/site.dist}" ;;
/etc/angie/site/* ) echo "${2:-/etc/angie/site.d}${1#/etc/angie/site}" ;;
/angie/site/* ) echo "${2:-/etc/angie/site.d}${1#/angie/site}" ;;
## snip
/etc/angie/snip.dist/* ) echo "${2:-/etc/angie/snip.d}${1#/etc/angie/snip.dist}" ;;
/etc/angie/snip/* ) echo "${2:-/etc/angie/snip.d}${1#/etc/angie/snip}" ;;
/angie/snip/* ) echo "${2:-/etc/angie/snip.d}${1#/angie/snip}" ;;
## static
/etc/angie/static.dist/* ) echo "${2:-/etc/angie/static.d}${1#/etc/angie/static.dist}" ;;
/etc/angie/static/* ) echo "${2:-/etc/angie/static.d}${1#/etc/angie/static}" ;;
/angie/static/* ) echo "${2:-/etc/angie/static.d}${1#/angie/static}" ;;
## log
/etc/angie/log.dist/* ) echo "${2:-/etc/angie/log.d}${1#/etc/angie/log.dist}" ;;
/angie/log/* ) echo "${2:-/etc/angie/log.d}${1#/angie/log}" ;;
## misbehavior!
* )
log_always "remap_path() doesn't know how to handle this path: $1"
return 1
;;
esac
}
combine_remap_path() {
[ -n "$1" ] || return
case "$1" in
"${merged_root}"/* ) echo "${2:-${target_root}}${1#"${merged_root}"}" ;;
## misbehavior!
* )
log_always "combine_remap_path() doesn't know how to handle this path: $1"
return 1
;;
esac
}
is_builtin_module() { is_builtin_module() {
[ -n "${1:-}" ] || return 1 [ -n "${1:-}" ] || return 1
[ -n "${2:-}" ] || return 1 [ -n "${2:-}" ] || return 1
@ -281,6 +184,30 @@ is_builtin_module() {
grep -Fxq -e "$2" "/etc/angie/builtin.$1" || return 1 grep -Fxq -e "$2" "/etc/angie/builtin.$1" || return 1
} }
append_list() {
if [ -n "$2" ] ; then
printf '%s' "${1:-}${1:+ }$2"
else
printf '%s' "$1"
fi
}
prepend_list() {
if [ -n "$2" ] ; then
printf '%s' "$2${1:+ }${1:-}"
else
printf '%s' "$1"
fi
}
list_have_item() {
[ -n "$2" ] || return 1
case " $1 " in
*" $2 "* ) return 0 ;;
* ) return 1 ;;
esac
}
normalize_list() { normalize_list() {
[ -n "$1" ] || return 0 [ -n "$1" ] || return 0
@ -296,3 +223,7 @@ sort_dedup_list() {
| tr -s '[:space:]' '\n' | sort -uV | paste -sd ' ' \ | tr -s '[:space:]' '\n' | sort -uV | paste -sd ' ' \
| sed -zE 's/^\s+//;s/\s+$//' | sed -zE 's/^\s+//;s/\s+$//'
} }
float_div() {
mawk -v "a=$1" -v "b=$2" 'BEGIN{print a/b;exit;}' </dev/null
}

View File

@ -28,29 +28,46 @@ else
NGX_DIRS_LINK="${NGX_DIRS_LINK:-} static" NGX_DIRS_LINK="${NGX_DIRS_LINK:-} static"
fi fi
set -a
NGX_DIRS_MERGE=$(sort_dedup_list "${default_dirs_merge} ${NGX_DIRS_MERGE:-}") NGX_DIRS_MERGE=$(sort_dedup_list "${default_dirs_merge} ${NGX_DIRS_MERGE:-}")
NGX_DIRS_LINK=$(sort_dedup_list "${default_dirs_link} ${NGX_DIRS_LINK:-}") NGX_DIRS_LINK=$(sort_dedup_list "${default_dirs_link} ${NGX_DIRS_LINK:-}")
set +a
unset default_dirs_merge default_dirs_link unset default_dirs_merge default_dirs_link
unset i dirs_link unset i dirs
dirs_link=
for i in ${NGX_DIRS_LINK:-} ; do dirs=
for i in ${NGX_DIRS_MERGE:-} ; do
[ -n "$i" ] || continue [ -n "$i" ] || continue
## naive deduplication case "$i" in
case " ${NGX_DIRS_MERGE} " in /* | */.* | *./* | *\** | *\?* )
*" $i "* ) log_always "NGX_DIRS_MERGE: dir '$i' is not legal, skipping"
log "$i is already specified in NGX_DIRS_MERGE - removing from NGX_DIRS_LINK"
continue continue
;; ;;
esac esac
dirs_link="${dirs_link}${dirs_link:+ }$i" dirs=$(append_list "${dirs}" "$i")
done done
unset i export NGX_DIRS_MERGE="${dirs}"
export NGX_DIRS_LINK="${dirs_link}" dirs=
unset dirs_link for i in ${NGX_DIRS_LINK:-} ; do
[ -n "$i" ] || continue
case "$i" in
/* | */.* | *./* | *\** | *\?* )
log_always "NGX_DIRS_LINK: dir '$i' is not legal, skipping"
continue
;;
esac
if list_have_item "${NGX_DIRS_MERGE}" "$i" ; then
log "$i is already specified in NGX_DIRS_MERGE - removing from NGX_DIRS_LINK"
continue
fi
dirs=$(append_list "${dirs}" "$i")
done
export NGX_DIRS_LINK="${dirs}"
unset i dirs

View File

@ -6,17 +6,17 @@
if [ -z "${NGX_IP_ADDRESSES:-}" ] ; then if [ -z "${NGX_IP_ADDRESSES:-}" ] ; then
NGX_IP_ADDRESSES=$(hostname -I) NGX_IP_ADDRESSES=$(hostname -I)
fi fi
NGX_IP_ADDRESSES=$(printf '%s' "${NGX_IP_ADDRESSES}" | sed -zE 's/^\s+//;s/\s+$//;s/\s+/ /g') NGX_IP_ADDRESSES=$(normalize_list "${NGX_IP_ADDRESSES}")
export NGX_IP_ADDRESSES export NGX_IP_ADDRESSES
unset NGX_IPV4_ADDRESSES NGX_IPV6_ADDRESSES unset NGX_IPV4_ADDRESSES NGX_IPV6_ADDRESSES
for i in ${NGX_IP_ADDRESSES} ; do for i in ${NGX_IP_ADDRESSES} ; do
case "$i" in case "$i" in
*:* ) *:* )
NGX_IPV6_ADDRESSES="${NGX_IPV6_ADDRESSES:-}${NGX_IPV6_ADDRESSES:+ }$i" NGX_IPV6_ADDRESSES=$(append_list "${NGX_IPV6_ADDRESSES}" "$i")
;; ;;
* ) * )
NGX_IPV4_ADDRESSES="${NGX_IPV4_ADDRESSES:-}${NGX_IPV4_ADDRESSES:+ }$i" NGX_IPV4_ADDRESSES=$(append_list "${NGX_IPV4_ADDRESSES}" "$i")
;; ;;
esac esac
done done

View File

@ -18,19 +18,17 @@ for i in ${NGX_CORE_MODULES:-} ; do
if is_builtin_module core "$i" ; then if is_builtin_module core "$i" ; then
log "$i is builtin module, moving to NGX_CORE_CONFLOAD" log "$i is builtin module, moving to NGX_CORE_CONFLOAD"
core_confload="${core_confload} $i" core_confload=$(append_list "${core_confload}" "$i")
continue continue
fi fi
## naive deduplication ## naive deduplication
case " ${core_modules} " in if list_have_item "${core_modules}" "$i" ; then
*" $i "* )
log "$i is already specified" log "$i is already specified"
continue continue
;; fi
esac
core_modules="${core_modules}${core_modules:+ }$i" core_modules=$(append_list "${core_modules}" "$i")
done done
unset i unset i

View File

@ -182,7 +182,7 @@ fi
if [ ${nofile_limit} -lt ${NGX_WORKER_CONNECTIONS} ] ; then if [ ${nofile_limit} -lt ${NGX_WORKER_CONNECTIONS} ] ; then
log_always "WARNING: ${nofile_kind} is less than NGX_WORKER_CONNECTIONS (${nofile_limit} < ${NGX_WORKER_CONNECTIONS})" log_always "WARNING: ${nofile_kind} is less than NGX_WORKER_CONNECTIONS (${nofile_limit} < ${NGX_WORKER_CONNECTIONS})"
else else
ratio=$(mawk -v "a=${nofile_limit}" -v "b=${NGX_WORKER_CONNECTIONS}" 'BEGIN{print a/b;exit;}' </dev/null) ratio=$(float_div "${nofile_limit}" "${NGX_WORKER_CONNECTIONS}")
case "${ratio}" in case "${ratio}" in
1 | 1.* ) 1 | 1.* )
log_always "WARNING: \"${nofile_kind}/NGX_WORKER_CONNECTIONS\" ratio is too low (=${ratio})" log_always "WARNING: \"${nofile_kind}/NGX_WORKER_CONNECTIONS\" ratio is too low (=${ratio})"

View File

@ -1,6 +1,8 @@
#!/bin/sh #!/bin/sh
if [ "${NGX_HTTP}" = 1 ] ; then if [ "${NGX_HTTP}" = 0 ] ; then
unset NGX_HTTP_NO_PROXY NGX_HTTP_WITH_MODSECURITY
else
unset http_modules http_confload unset http_modules http_confload
http_modules= http_modules=
http_confload="${NGX_HTTP_CONFLOAD:-}" http_confload="${NGX_HTTP_CONFLOAD:-}"
@ -8,6 +10,18 @@ if [ "${NGX_HTTP}" = 1 ] ; then
if [ -n "${NGX_HTTP_MODULES}" ] ; then if [ -n "${NGX_HTTP_MODULES}" ] ; then
## angie-module-lua: depends on angie-module-ndk ## angie-module-lua: depends on angie-module-ndk
## angie-module-set-misc: depends on angie-module-ndk ## angie-module-set-misc: depends on angie-module-ndk
# unset want_ndk
# want_ndk=0
# if list_have_item "${NGX_HTTP_MODULES}" lua ; then
# want_ndk=1
# elif list_have_item "${NGX_HTTP_MODULES}" set-misc ; then
# want_ndk=1
# fi
# if [ ${want_ndk} = 1 ] ; then
# NGX_HTTP_MODULES=$(prepend_list "${NGX_HTTP_MODULES}" ndk)
# fi
# unset want_ndk
NGX_HTTP_MODULES=$( NGX_HTTP_MODULES=$(
printf '%s' "${NGX_HTTP_MODULES}" \ printf '%s' "${NGX_HTTP_MODULES}" \
| sed -zE 's/(\s|^)(lua|set-misc)(\s|$)/\1ndk \2\3/g' | sed -zE 's/(\s|^)(lua|set-misc)(\s|$)/\1ndk \2\3/g'
@ -28,19 +42,17 @@ if [ "${NGX_HTTP}" = 1 ] ; then
if is_builtin_module http "$i" ; then if is_builtin_module http "$i" ; then
log "$i is builtin module, moving to NGX_HTTP_CONFLOAD" log "$i is builtin module, moving to NGX_HTTP_CONFLOAD"
http_confload="${http_confload} $i" http_confload=$(append_list "${http_confload}" "$i")
continue continue
fi fi
## naive deduplication ## naive deduplication
case " ${http_modules} " in if list_have_item "${http_modules}" "$i" ; then
*" $i "* )
log "$i is already specified" log "$i is already specified"
continue continue
;; fi
esac
http_modules="${http_modules}${http_modules:+ }$i" http_modules=$(append_list "${http_modules}" "$i")
done done
unset i unset i
@ -55,14 +67,14 @@ if [ "${NGX_HTTP}" = 1 ] ; then
unset NGX_HTTP_WITH_MODSECURITY unset NGX_HTTP_WITH_MODSECURITY
NGX_HTTP_WITH_MODSECURITY=0 NGX_HTTP_WITH_MODSECURITY=0
while : ; do while : ; do
case " ${NGX_HTTP_MODULES} " in if ! list_have_item "${NGX_HTTP_MODULES}" modsecurity ; then
*" modsecurity "* ) ;; break
* ) break ;; fi
esac
for d in /angie/modules /etc/angie/modules /etc/angie/modules.dist ; do for d in /angie/modules /etc/angie/modules /etc/angie/modules.dist ; do
[ -d "$d" ] || continue [ -d "$d" ] || continue
if [ -f "$d/ngx_http_modsecurity_module.so" ] ; then [ -f "$d/ngx_http_modsecurity_module.so" ] || continue
if ! [ -h "$d/ngx_http_modsecurity_module.so" ] ; then
NGX_HTTP_WITH_MODSECURITY=1 NGX_HTTP_WITH_MODSECURITY=1
break break
fi fi

View File

@ -19,19 +19,17 @@ if [ "${NGX_MAIL}" = 1 ] ; then
if is_builtin_module mail "$i" ; then if is_builtin_module mail "$i" ; then
log "$i is builtin module, moving to NGX_MAIL_CONFLOAD" log "$i is builtin module, moving to NGX_MAIL_CONFLOAD"
mail_confload="${mail_confload} $i" mail_confload=$(append_list "${mail_confload}" "$i")
continue continue
fi fi
## naive deduplication ## naive deduplication
case " ${mail_modules} " in if list_have_item "${mail_modules}" "$i" ; then
*" $i "* )
log "$i is already specified" log "$i is already specified"
continue continue
;; fi
esac
mail_modules="${mail_modules}${mail_modules:+ }$i" mail_modules=$(append_list "${mail_modules}" "$i")
done done
unset i unset i

View File

@ -19,19 +19,17 @@ if [ "${NGX_STREAM}" = 1 ] ; then
if is_builtin_module stream "$i" ; then if is_builtin_module stream "$i" ; then
log "$i is builtin module, moving to NGX_STREAM_CONFLOAD" log "$i is builtin module, moving to NGX_STREAM_CONFLOAD"
stream_confload="${stream_confload} $i" stream_confload=$(append_list "${stream_confload}" "$i")
continue continue
fi fi
## naive deduplication ## naive deduplication
case " ${stream_modules} " in if list_have_item "${stream_modules}" "$i" ; then
*" $i "* )
log "$i is already specified" log "$i is already specified"
continue continue
;; fi
esac
stream_modules="${stream_modules}${stream_modules:+ }$i" stream_modules=$(append_list "${stream_modules}" "$i")
done done
unset i unset i

View File

@ -5,6 +5,22 @@ set -ef
[ -d "${merged_root}" ] || install -d "${merged_root}" [ -d "${merged_root}" ] || install -d "${merged_root}"
remap_path_int() {
printf '%s' "$2/${1#*/}"
}
remap_path() {
case "$1" in
/etc/angie/* ) remap_path_int "${1#/etc/angie/}" "$2" ;;
/angie/* ) remap_path_int "${1#/angie/}" "$2" ;;
## misbehavior!
* )
log_always "remap_path() doesn't know how to handle this path: '$1'"
return 1
;;
esac
}
for n in ${NGX_DIRS_MERGE} ; do for n in ${NGX_DIRS_MERGE} ; do
[ -n "$n" ] || continue [ -n "$n" ] || continue

View File

@ -13,6 +13,7 @@ cd "${merged_root}/"
expand_error_delim() { expand_error_delim() {
IEP_DEBUG=0 log_always ' ----------------------------------- ' IEP_DEBUG=0 log_always ' ----------------------------------- '
} }
unset expand_error_seen
expand_error() { expand_error() {
[ "${expand_error_seen:-}" != 1 ] || return [ "${expand_error_seen:-}" != 1 ] || return
expand_error_seen=1 expand_error_seen=1

View File

@ -8,6 +8,7 @@ set -f
load_error_delim() { load_error_delim() {
IEP_DEBUG=0 log_always ' ----------------------------------- ' IEP_DEBUG=0 log_always ' ----------------------------------- '
} }
unset load_error_seen
load_error() { load_error() {
[ "${load_error_seen:-}" != 1 ] || return [ "${load_error_seen:-}" != 1 ] || return
load_error_seen=1 load_error_seen=1
@ -47,7 +48,7 @@ for p in ${dirs} ; do
[ -d "$d/$p" ] || install_userdir "$d/$p" || load_error [ -d "$d/$p" ] || install_userdir "$d/$p" || load_error
done done
if [ "${NGX_HTTP_WITH_MODSECURITY}" = 1 ] ; then if [ "${NGX_HTTP_WITH_MODSECURITY:-}" = 1 ] ; then
d="${target_root}/log" d="${target_root}/log"
for p in modsecurity modsecurity/concurrent ; do for p in modsecurity modsecurity/concurrent ; do
[ -d "$d/$p" ] || install_userdir "$d/$p" || load_error [ -d "$d/$p" ] || install_userdir "$d/$p" || load_error
@ -61,10 +62,23 @@ d="${target_root}/log"
## NB: if any error occurs above then configuration is merely empty and/or broken ## NB: if any error occurs above then configuration is merely empty and/or broken
remap_path() {
[ -n "$1" ] || return
case "$1" in
"${merged_root}"/* ) echo "${target_root}${1#"${merged_root}"}" ;;
## misbehavior!
* )
log_always "remap_path() doesn't know how to handle this path: $1"
return 1
;;
esac
}
while read -r old_path ; do while read -r old_path ; do
[ -n "${old_path}" ] || continue [ -n "${old_path}" ] || continue
new_path=$(combine_remap_path "${old_path}") new_path=$(remap_path "${old_path}")
[ -n "${new_path}" ] [ -n "${new_path}" ]
new_dir="${new_path%/*}" new_dir="${new_path%/*}"

View File

@ -16,19 +16,19 @@ def is_mapping(x) -> bool:
return isinstance(x, collections.abc.Mapping) return isinstance(x, collections.abc.Mapping)
def uniq(a: (list, set)) -> list: def uniq(a: list | set) -> list:
return list(dict.fromkeys(a)) return sorted(set(a))
def remove_non_str(a: (list, set)) -> list: def remove_non_str(a: list | set) -> list:
return list(filter(lambda x: isinstance(x, str), a)) return list(filter(lambda x: isinstance(x, str), a))
def remove_empty_str(a: (list, set)) -> list: def remove_empty_str(a: list | set) -> list:
return list(filter(None, a)) return list(filter(None, a))
def uniq_str_list(a: (list, set)) -> (list, set): def uniq_str_list(a: list | set) -> list:
return remove_empty_str(uniq(a)) return remove_empty_str(uniq(a))
@ -47,15 +47,14 @@ def dict_to_env_str_list(x: dict) -> list:
def any_to_str_list(x) -> list: def any_to_str_list(x) -> list:
if x is None:
return []
if isinstance(x, str): if isinstance(x, str):
return [x] return [x]
if is_sequence(x): if is_sequence(x):
return [str(e) for e in x] return [str(e) for e in x]
if is_mapping(x): if is_mapping(x):
return dict_to_env_str_list(x) return dict_to_env_str_list(x)
return [str(x)] return [str(x)]
@ -130,21 +129,16 @@ def re_fullmatch_negate(x, pattern, flags=0):
def dict_remap_keys(x: dict, key_map) -> dict: def dict_remap_keys(x: dict, key_map) -> dict:
if key_map is None: if key_map is None:
return x return x
all_keys = list(x.keys()) p = set(x.keys())
kmap = { m = {}
k: key_map(k) for k in x:
for k in all_keys v = key_map(k)
if k != key_map(k) if v == k:
} continue
persist_keys = [ m[k] = v
k for k in all_keys p.discard(k)
if k not in kmap.keys() and k not in kmap.values() p.discard(v)
] return {k: x[k] for k in p} | {v: x[k] for k, v in m.items()}
return {
k: x[k] for k in persist_keys
} | {
k: x[v] for k, v in kmap.items()
}
def re_sub(x, pattern, repl, count=0, flags=0): def re_sub(x, pattern, repl, count=0, flags=0):
@ -184,9 +178,11 @@ def any_to_env_dict(x) -> dict:
h = {} h = {}
def feed(k, v=None): def feed(k, parse=False, v=None):
k = str(k)
if v is None: if v is None:
return
k = str(k)
if parse:
k2, m, v2 = k.partition('=') k2, m, v2 = k.partition('=')
if m == '=': if m == '=':
k = k2 k = k2
@ -200,13 +196,13 @@ def any_to_env_dict(x) -> dict:
h[k] = v if v is None else str(v) h[k] = v if v is None else str(v)
if isinstance(x, str): if isinstance(x, str):
feed(x) feed(x, True)
elif is_sequence(x): elif is_sequence(x):
for e in x: for e in x:
feed(e) feed(e, True)
elif is_mapping(x): elif is_mapping(x):
for k in x: for k in x:
feed(k, x[k]) feed(k, False, x[k])
else: else:
return {} return {}
@ -225,11 +221,11 @@ def dict_non_empty_keys(x: dict) -> list:
return sorted([k for k in x.keys() if x[k] is not None]) return sorted([k for k in x.keys() if x[k] is not None])
def list_diff(a: (list, set), b: (list, set)) -> list: def list_diff(a: list | set, b: list | set) -> list:
return list(set(a) - set(b)) return list(set(a) - set(b))
def list_intersect(a: (list, set), b: (list, set)) -> list: def list_intersect(a: list | set, b: list | set) -> list:
return list(set(a) & set(b)) return list(set(a) & set(b))