|
|
@ -32,11 +32,10 @@ |
|
|
|
} |
|
|
|
#:- |
|
|
|
|
|
|
|
|
|
|
|
include pretty |
|
|
|
include parse |
|
|
|
|
|
|
|
md5_compat() { md5sum | cut -c -32; } |
|
|
|
|
|
|
|
depends shyaml docker |
|
|
|
|
|
|
|
[[ "${BASH_SOURCE[0]}" != "${0}" ]] && SOURCED=true |
|
|
@ -45,8 +44,11 @@ depends shyaml docker |
|
|
|
export CACHEDIR=/var/cache/compose |
|
|
|
export VARDIR=/var/lib/compose |
|
|
|
|
|
|
|
mkdir -p "$CACHEDIR" || exit 1 |
|
|
|
|
|
|
|
md5_compat() { md5sum | cut -c -32; } |
|
|
|
quick_cat_file() { quick_cat_stdin < "$1"; } |
|
|
|
quick_cat_stdin() { local IFS=''; while read -r line; do echo "$line"; done ; } |
|
|
|
export -f quick_cat_file quick_cat_stdin md5_compat |
|
|
|
|
|
|
|
trap_add "EXIT" clean_cache |
|
|
|
|
|
|
|
usage="$exname CHARM"' |
|
|
@ -203,7 +205,7 @@ export -f yaml_key_val_str |
|
|
|
|
|
|
|
|
|
|
|
## |
|
|
|
## Functions |
|
|
|
## Docker |
|
|
|
## |
|
|
|
|
|
|
|
docker_has_image() { |
|
|
@ -216,6 +218,44 @@ docker_has_image() { |
|
|
|
} |
|
|
|
export -f docker_has_image |
|
|
|
|
|
|
|
cmd_on_base_image() { |
|
|
|
local charm="$1" |
|
|
|
shift |
|
|
|
base_image=$(service_base_docker_image "$charm") || return 1 |
|
|
|
|
|
|
|
docker run -i --entrypoint /bin/bash "$base_image" -c "$*" |
|
|
|
} |
|
|
|
export -f cmd_on_base_image |
|
|
|
|
|
|
|
cached_cmd_on_base_image() { |
|
|
|
local charm="$1" cache_file="$state_tmpdir/$FUNCNAME.cache.$(echo "$*" | md5_compat)" |
|
|
|
shift |
|
|
|
if [ -e "$cache_file" ]; then |
|
|
|
# debug "$FUNCNAME: cache hit ($*)" |
|
|
|
quick_cat_stdin < "$cache_file" |
|
|
|
return 0 |
|
|
|
fi |
|
|
|
base_image=$(service_base_docker_image "$charm") || return 1 |
|
|
|
result=$(cmd_on_base_image "$charm" "$@") || return 1 |
|
|
|
echo "$result" | tee "$cache_file" |
|
|
|
} |
|
|
|
export -f cached_cmd_on_base_image |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## |
|
|
|
## Generic |
|
|
|
## |
|
|
|
|
|
|
|
str_matches() { |
|
|
|
local str="$1" |
|
|
|
shift |
|
|
|
for pattern in "$@"; do |
|
|
|
eval "[[ \"$str\" == $pattern ]]" && return 0 |
|
|
|
done |
|
|
|
return 1 |
|
|
|
} |
|
|
|
|
|
|
|
gen_password() { |
|
|
|
python -c 'import random; \ |
|
|
|
xx = "azertyuiopqsdfghjklmwxcvbn1234567890AZERTYUIOPQSDFGHJKLMWXCVBN+_-"; \ |
|
|
@ -232,6 +272,129 @@ file_put() { |
|
|
|
export -f file_put |
|
|
|
|
|
|
|
|
|
|
|
file_put_0() { |
|
|
|
local TARGET="$1" |
|
|
|
mkdir -p "$(dirname "$TARGET")" && |
|
|
|
cat > "$TARGET" |
|
|
|
} |
|
|
|
export -f file_put_0 |
|
|
|
|
|
|
|
fetch_file() { |
|
|
|
local src="$1" |
|
|
|
|
|
|
|
case "$src" in |
|
|
|
*"://"*) |
|
|
|
err "Unsupported target scheme." |
|
|
|
return 1 |
|
|
|
;; |
|
|
|
*) |
|
|
|
## Try direct |
|
|
|
if ! [ -r "$src" ]; then |
|
|
|
err "File '$src' not found/readable." |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
cat "$src" || return 1 |
|
|
|
;; |
|
|
|
esac |
|
|
|
} |
|
|
|
export -f fetch_file |
|
|
|
|
|
|
|
## receives stdin content to decompress on stdout |
|
|
|
## stdout content should be tar format. |
|
|
|
uncompress_file() { |
|
|
|
local filename="$1" |
|
|
|
|
|
|
|
## Warning, the content of the file is already as stdin, the filename |
|
|
|
## is there to hint for correct decompression. |
|
|
|
case "$filename" in |
|
|
|
*".gz") |
|
|
|
gunzip |
|
|
|
;; |
|
|
|
*".bz2") |
|
|
|
bunzip2 |
|
|
|
;; |
|
|
|
*) |
|
|
|
cat |
|
|
|
;; |
|
|
|
esac |
|
|
|
|
|
|
|
} |
|
|
|
export -f uncompress_file |
|
|
|
|
|
|
|
get_file() { |
|
|
|
local src="$1" |
|
|
|
|
|
|
|
fetch_file "$src" | uncompress_file "$src" |
|
|
|
} |
|
|
|
export -f get_file |
|
|
|
|
|
|
|
|
|
|
|
## |
|
|
|
## Arrays |
|
|
|
## |
|
|
|
|
|
|
|
array_values_to_stdin() { |
|
|
|
local e |
|
|
|
if [ "$#" -ne "1" ]; then |
|
|
|
print_syntax_warning "$FUNCNAME: need one argument." |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
var="$1" |
|
|
|
eval "for e in \"\${$var[@]}\"; do echo -en \"\$e\\0\"; done" |
|
|
|
} |
|
|
|
|
|
|
|
array_keys_to_stdin() { |
|
|
|
local e |
|
|
|
if [ "$#" -ne "1" ]; then |
|
|
|
print_syntax_warning "$FUNCNAME: need one argument." |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
var="$1" |
|
|
|
eval "for e in \"\${!$var[@]}\"; do echo -en \"\$e\\0\"; done" |
|
|
|
} |
|
|
|
|
|
|
|
array_kv_to_stdin() { |
|
|
|
local e |
|
|
|
if [ "$#" -ne "1" ]; then |
|
|
|
print_syntax_warning "$FUNCNAME: need one argument." |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
var="$1" |
|
|
|
eval "for e in \"\${!$var[@]}\"; do echo -n \"\$e\"; echo -en '\0'; echo -n \"\${$var[\$e]}\"; echo -en '\0'; done" |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
array_pop() { |
|
|
|
local narr="$1" nres="$2" |
|
|
|
for key in $(eval "echo \${!$narr[@]}"); do |
|
|
|
eval "$nres=\${$narr[\"\$key\"]}" |
|
|
|
eval "unset $narr[\"\$key\"]" |
|
|
|
return 0 |
|
|
|
done |
|
|
|
} |
|
|
|
export -f array_pop |
|
|
|
|
|
|
|
array_member() { |
|
|
|
local src elt |
|
|
|
src="$1" |
|
|
|
elt="$2" |
|
|
|
while read-0 key; do |
|
|
|
if [ "$(eval "echo -n \"\${$src[\$key]}\"")" == "$elt" ]; then |
|
|
|
return 0 |
|
|
|
fi |
|
|
|
done < <(array_keys_to_stdin "$src") |
|
|
|
return 1 |
|
|
|
} |
|
|
|
export -f array_member |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## |
|
|
|
## Internal Process |
|
|
|
## |
|
|
|
|
|
|
|
|
|
|
|
get_docker_compose_links() { |
|
|
|
local service="$1" cache_file="$state_tmpdir/$FUNCNAME.cache.$1" \ |
|
|
|
links charm charm_part master_charm |
|
|
@ -501,145 +664,6 @@ service_base_docker_image() { |
|
|
|
} |
|
|
|
export -f service_base_docker_image |
|
|
|
|
|
|
|
## XXXvlab: provided in shlib/common |
|
|
|
# read-0() { |
|
|
|
# local eof |
|
|
|
# eof= |
|
|
|
# while [ "$1" ]; do |
|
|
|
# IFS='' read -r -d '' "$1" || eof=true |
|
|
|
# shift |
|
|
|
# done |
|
|
|
# test "$eof" != true |
|
|
|
# } |
|
|
|
# export -f read-0 |
|
|
|
|
|
|
|
fetch_file() { |
|
|
|
local src="$1" |
|
|
|
|
|
|
|
case "$src" in |
|
|
|
*"://"*) |
|
|
|
err "Unsupported target scheme." |
|
|
|
return 1 |
|
|
|
;; |
|
|
|
*) |
|
|
|
## Try direct |
|
|
|
if ! [ -r "$src" ]; then |
|
|
|
err "File '$src' not found/readable." |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
cat "$src" || return 1 |
|
|
|
;; |
|
|
|
esac |
|
|
|
} |
|
|
|
export -f fetch_file |
|
|
|
|
|
|
|
## receives stdin content to decompress on stdout |
|
|
|
## stdout content should be tar format. |
|
|
|
uncompress_file() { |
|
|
|
local filename="$1" |
|
|
|
|
|
|
|
## Warning, the content of the file is already as stdin, the filename |
|
|
|
## is there to hint for correct decompression. |
|
|
|
case "$filename" in |
|
|
|
*".gz") |
|
|
|
gunzip |
|
|
|
;; |
|
|
|
*".bz2") |
|
|
|
bunzip2 |
|
|
|
;; |
|
|
|
*) |
|
|
|
cat |
|
|
|
;; |
|
|
|
esac |
|
|
|
|
|
|
|
} |
|
|
|
export -f uncompress_file |
|
|
|
|
|
|
|
get_file() { |
|
|
|
local src="$1" |
|
|
|
|
|
|
|
fetch_file "$src" | uncompress_file "$src" |
|
|
|
} |
|
|
|
export -f get_file |
|
|
|
|
|
|
|
|
|
|
|
cmd_on_base_image() { |
|
|
|
local charm="$1" |
|
|
|
shift |
|
|
|
base_image=$(service_base_docker_image "$charm") || return 1 |
|
|
|
|
|
|
|
docker run -i --entrypoint /bin/bash "$base_image" -c "$*" |
|
|
|
} |
|
|
|
export -f cmd_on_base_image |
|
|
|
|
|
|
|
cached_cmd_on_base_image() { |
|
|
|
local charm="$1" cache_file="$state_tmpdir/$FUNCNAME.cache.$(echo "$*" | md5_compat)" |
|
|
|
shift |
|
|
|
if [ -e "$cache_file" ]; then |
|
|
|
# debug "$FUNCNAME: cache hit ($*)" |
|
|
|
cat "$cache_file" |
|
|
|
return 0 |
|
|
|
fi |
|
|
|
base_image=$(service_base_docker_image "$charm") || return 1 |
|
|
|
result=$(cmd_on_base_image "$charm" "$@") || return 1 |
|
|
|
echo "$result" | tee "$cache_file" |
|
|
|
} |
|
|
|
export -f cached_cmd_on_base_image |
|
|
|
|
|
|
|
array_values_to_stdin() { |
|
|
|
local e |
|
|
|
if [ "$#" -ne "1" ]; then |
|
|
|
print_syntax_warning "$FUNCNAME: need one argument." |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
var="$1" |
|
|
|
eval "for e in \"\${$var[@]}\"; do echo -en \"\$e\\0\"; done" |
|
|
|
} |
|
|
|
|
|
|
|
array_keys_to_stdin() { |
|
|
|
local e |
|
|
|
if [ "$#" -ne "1" ]; then |
|
|
|
print_syntax_warning "$FUNCNAME: need one argument." |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
var="$1" |
|
|
|
eval "for e in \"\${!$var[@]}\"; do echo -en \"\$e\\0\"; done" |
|
|
|
} |
|
|
|
|
|
|
|
array_kv_to_stdin() { |
|
|
|
local e |
|
|
|
if [ "$#" -ne "1" ]; then |
|
|
|
print_syntax_warning "$FUNCNAME: need one argument." |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
var="$1" |
|
|
|
eval "for e in \"\${!$var[@]}\"; do echo -n \"\$e\"; echo -en '\0'; echo -n \"\${$var[\$e]}\"; echo -en '\0'; done" |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
array_pop() { |
|
|
|
local narr="$1" nres="$2" |
|
|
|
for key in $(eval "echo \${!$narr[@]}"); do |
|
|
|
eval "$nres=\${$narr[\"\$key\"]}" |
|
|
|
eval "unset $narr[\"\$key\"]" |
|
|
|
return 0 |
|
|
|
done |
|
|
|
} |
|
|
|
export -f array_pop |
|
|
|
|
|
|
|
array_member() { |
|
|
|
local src elt |
|
|
|
src="$1" |
|
|
|
elt="$2" |
|
|
|
while read-0 key; do |
|
|
|
if [ "$(eval "echo -n \"\${$src[\$key]}\"")" == "$elt" ]; then |
|
|
|
return 0 |
|
|
|
fi |
|
|
|
done < <(array_keys_to_stdin "$src") |
|
|
|
return 1 |
|
|
|
} |
|
|
|
export -f array_member |
|
|
|
|
|
|
|
|
|
|
|
get_charm_relation_def () { |
|
|
|
local charm="$1" relation_name="$2" cache_file="$state_tmpdir/$FUNCNAME.cache.$1.$2" \ |
|
|
@ -1655,7 +1679,9 @@ _setup_state_dir() { |
|
|
|
trap_add EXIT "rm -rf \"$state_tmpdir\"" |
|
|
|
} |
|
|
|
|
|
|
|
## Returns arg list of an docker-compose |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get_docker_compose_opts_list() { |
|
|
|
local cache_file="$CACHEDIR/$FUNCNAME.cache.$(cat "$(which docker-compose)" | md5_compat)" |
|
|
|
if [ -e "$cache_file" ]; then |
|
|
@ -1698,18 +1724,8 @@ clean_cache() { |
|
|
|
fi |
|
|
|
} |
|
|
|
|
|
|
|
str_matches() { |
|
|
|
local str="$1" |
|
|
|
shift |
|
|
|
for pattern in "$@"; do |
|
|
|
eval "[[ \"$str\" == $pattern ]]" && return 0 |
|
|
|
done |
|
|
|
return 1 |
|
|
|
} |
|
|
|
|
|
|
|
[ "$SOURCED" ] && return 0 |
|
|
|
|
|
|
|
|
|
|
|
if [ -z "$DISABLE_SYSTEM_CONFIG_FILE" ]; then |
|
|
|
if [ -r /etc/default/charm ]; then |
|
|
|
. /etc/default/charm |
|
|
@ -1726,6 +1742,7 @@ if [ -z "$DISABLE_SYSTEM_CONFIG_FILE" ]; then |
|
|
|
fi |
|
|
|
|
|
|
|
_setup_state_dir |
|
|
|
mkdir -p "$CACHEDIR" || exit 1 |
|
|
|
|
|
|
|
## |
|
|
|
## Argument parsing |
|
|
|