From aded4a7dde8282fd73ef65ef4b171228e04a2521 Mon Sep 17 00:00:00 2001 From: Valentin Lab Date: Mon, 20 Feb 2023 19:08:48 +0100 Subject: [PATCH] new: [compose-core] add ``memory.limit`` metadata value to limit container's memory --- bin/compose-core | 95 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/bin/compose-core b/bin/compose-core index 9e58d77..34d5406 100755 --- a/bin/compose-core +++ b/bin/compose-core @@ -108,6 +108,50 @@ quick_cat_stdin() { local IFS=''; while read -r line; do echo "$line"; done ; } export -f quick_cat_file quick_cat_stdin md5_compat +read-0-err() { + local ret="$1" eof="" idx=0 last= + read -r -- "${ret?}" <<<"0" + shift + while [ "$1" ]; do + last=$idx + read -r -d '' -- "$1" || { + ## Put this last value in ${!ret} + eof="$1" + read -r -- "$ret" <<<"${!eof}" + break + } + ((idx++)) + shift + done + [ -z "$eof" ] || { + if [ "$last" != 0 ]; then + echo "Error: read-0-err couldn't fill all value" >&2 + read -r -- "$ret" <<<"127" + else + if [ -z "${!ret}" ]; then + echo "Error: last value is not a number, did you finish with an errorlevel ?" >&2 + read -r -- "$ret" <<<"126" + fi + fi + false + } +} + + +wyq() { + local exp="$1" + yq e -e -0 "$1" + printf "%s" "$?" +} + + +wyq-r() { + local exp="$1" + yq e -e -0 -r=false "$1" + printf "%s" "$?" +} + + clean_cache() { local i=0 for f in $(ls -t "$CACHEDIR/"*.cache.* 2>/dev/null | tail -n +500); do @@ -3187,7 +3231,8 @@ _get_docker_compose_mixin_from_metadata_cached() { local service="$1" charm="$2" metadata="$3" \ has_build_dir="$4" \ cache_file="$CACHEDIR/$FUNCNAME.cache.$(echo "$*" | md5_compat)" \ - metadata_file metadata volumes docker_compose subordinate image mixin mixins + metadata_file metadata volumes docker_compose subordinate image \ + mixin mixins tmemory memory limit docker_memory if [ -e "$cache_file" ]; then #debug "$FUNCNAME: STATIC cache hit $1" @@ -3260,6 +3305,54 @@ _get_docker_compose_mixin_from_metadata_cached() { fi mixins+=("build: $(charm.get_dir "$charm")/build") fi + limit=$(e "$metadata" | yq '.limit' 2>/dev/null) || return 1 + [ "$limit" == "null" ] && limit="" + if [ -n "$limit" ]; then + if ! read-0-err E tmemory memory < <(e "$limit" | wyq ".memory | type, .memory") || + [ "$E" != 0 ]; then + err "Unexpected error in ${DARKPINK}$charm${NORMAL}'s metadata when parsing ${WHITE}.limit${NORMAL}" + return 1 + fi + case "$tmemory" in + '!!str'|'!!int') + docker_memory="$(e "$memory" | numfmt --from iec)" || { + err "Invalid format specified for .limit.memory: '$memory'." + return 1 + } + ;; + '!!float') + err "Unexpected value in ${DARKPINK}$charm${NORMAL}'s metadata for ${WHITE}.limit.memory${NORMAL}." + echo " You need to specify a unit (like 'K', 'M', 'G' ...)." >&2 + return 1 + ;; + '!!null') + : + ;; + *) + err "Unexpected type '${tmemory#!!}' in ${DARKPINK}$charm${NORMAL}'s metadata" \ + "for ${WHITE}.limit.memory${NORMAL}." + echo " You need to check ${DARKPINK}$charm${NORMAL}'s metadata " \ + "for ${WHITE}.limit.memory${NORMAL} and provide a valid value" >&2 + echo " Example values: '1.5G', '252M', ..." >&2 + return 1 + ;; + esac + if [ -n "$docker_memory" ]; then + if [[ "$docker_memory" -lt 6291456 ]]; then + err "Can't limit service to lower than 6M." + echo " Specified limit of $memory (=$docker_memory) is lower than docker's min limit of 6M (=6291456)." >&2 + echo " The provided limit to memory is lower than minimum memory for a container." >&2 + echo " Please remove memory limit in ${DARKPINK}$charm${NORMAL}'s metadata or raise it." >&2 + return 1 + fi + mixins+=( + "mem_limit: $docker_memory" + "memswap_limit: $docker_memory" + ) + fi + fi + ## Final merging + mixin=$(merge_yaml_str "${mixins[@]}") || { err "Failed to merge mixins from ${DARKPINK}${charm}${NORMAL} metadata." return 1