From fbf0809a247291c3dc93e1cee4607db3662269db Mon Sep 17 00:00:00 2001 From: Shizun Ge Date: Fri, 19 Jan 2024 22:01:40 -0800 Subject: [PATCH] run the image of current container in the remove images step. --- src/entrypoint.sh | 28 +++++++++++++-- src/lib-gantry.sh | 86 +++++++++++++++++++++++++---------------------- 2 files changed, 71 insertions(+), 43 deletions(-) diff --git a/src/entrypoint.sh b/src/entrypoint.sh index d7276c3..ace2fb1 100755 --- a/src/entrypoint.sh +++ b/src/entrypoint.sh @@ -57,7 +57,7 @@ exec_pre_run_cmd() { log INFO "Run pre-run command: ${CMD}" LOG=$(eval "${CMD}") RT=$? - log INFO "${LOG}" + echo "${LOG}" | log_lines INFO log INFO "Finish pre-run command. Return value ${RT}." } @@ -68,10 +68,30 @@ exec_post_run_cmd() { log INFO "Run post-run command: ${CMD}" LOG=$(eval "${CMD}") RT=$? - log INFO "${LOG}" + echo "${LOG}" | log_lines INFO log INFO "Finish post-run command. Return value ${RT}." } +exec_remove_images() { + local IMAGES_TO_REMOVE="${1}" + local IMAGE RMI_MSG + for IMAGE in ${IMAGES_TO_REMOVE}; do + if ! docker image inspect "${IMAGE}" 1>/dev/null 2>&1 ; then + log DEBUG "There is no image ${IMAGE} on the node."; + continue; + fi; + remove_container "${IMAGE}" exited; + remove_container "${IMAGE}" dead; + if ! RMI_MSG=$(docker rmi "${IMAGE}" 2>&1); then + log ERROR "Failed to remove image ${IMAGE}."; + echo "${RMI_MSG}" | log_lines ERROR + continue; + fi; + log INFO "Removed image ${IMAGE}."; + done; + log INFO "Done."; +} + gantry() { local STACK="${1:-gantry}" local START_TIME= @@ -129,6 +149,10 @@ main() { LOG_LEVEL="${GANTRY_LOG_LEVEL:-${LOG_LEVEL}}" NODE_NAME="${GANTRY_NODE_NAME:-${NODE_NAME}}" export LOG_LEVEL NODE_NAME + if [ -n "${GANTRY_IMAGES_TO_REMOVE:-""}" ]; then + exec_remove_images "${GANTRY_IMAGES_TO_REMOVE}" + return $? + fi local INTERVAL_SECONDS="${GANTRY_SLEEP_SECONDS:-0}" if ! is_number "${INTERVAL_SECONDS}"; then log ERROR "GANTRY_SLEEP_SECONDS must be a number. Got \"${GANTRY_SLEEP_SECONDS}\"." diff --git a/src/lib-gantry.sh b/src/lib-gantry.sh index 10fb043..36caf8c 100755 --- a/src/lib-gantry.sh +++ b/src/lib-gantry.sh @@ -101,6 +101,27 @@ add_image_to_remove() { STATIC_VAR_IMAGES_TO_REMOVE=$(add_uniq_to_list "${STATIC_VAR_IMAGES_TO_REMOVE}" "${IMAGE}") } +remove_container() { + local IMAGE="${1}"; + local STATUS="${2}"; + local CIDS + if ! CIDS=$(docker container ls --all --filter "ancestor=${IMAGE}" --filter "status=${STATUS}" --format '{{.ID}}' 2>&1); then + log ERROR "Failed to list ${STATUS} containers with image ${IMAGE}."; + echo "${CIDS}" | log_lines ERROR + return 1; + fi; + local CID CNAME CRM_MSG + for CID in ${CIDS}; do + CNAME=$(docker container inspect --format '{{.Name}}' "${CID}"); + if ! CRM_MSG=$(docker container rm "${CID}" 2>&1); then + log ERROR "Failed to remove ${STATUS} container ${CNAME}, which is using image ${IMAGE}."; + echo "${CRM_MSG}" | log_lines ERROR + continue; + fi + log INFO "Removed ${STATUS} container ${CNAME}. It was using image ${IMAGE}."; + done; +}; + remove_images() { local CLEANUP_IMAGES="${GANTRY_CLEANUP_IMAGES:-"true"}" if ! is_true "${CLEANUP_IMAGES}"; then @@ -119,48 +140,15 @@ remove_images() { for I in $(echo "${STATIC_VAR_IMAGES_TO_REMOVE}" | tr '\n' ' '); do log INFO "- ${I}" done + local IMAGE_OF_THIS_CONTAINER= + IMAGE_OF_THIS_CONTAINER=$(get_service_image "$(current_service_name)") + [ -z "${IMAGE_OF_THIS_CONTAINER}" ] && IMAGE_OF_THIS_CONTAINER="shizunge/gantry" docker_global_job --name "${SERVICE_NAME}" \ --restart-condition on-failure \ --restart-max-attempts 1 \ --mount type=bind,source=/var/run/docker.sock,destination=/var/run/docker.sock \ - --env "IMAGES_TO_REMOVE=$(echo "${STATIC_VAR_IMAGES_TO_REMOVE}" | tr '\n' ' ')" \ - --entrypoint sh \ - alpinelinux/docker-cli \ - -c " - log() { - echo \"\${@}\"; - }; - remove_container() { - local IMAGE=\${1}; - local STATUS=\${2}; - if ! CIDS=\$(docker container ls --all --filter \"ancestor=\${IMAGE}\" --filter \"status=\${STATUS}\" --format '{{.ID}}' 2>&1); then - log ERROR \"Failed to list \${STATUS} containers with image \${IMAGE}. \$(echo \${CIDS})\"; - return 1; - fi; - for CID in \${CIDS}; do - CNAME=\$(docker container inspect --format '{{.Name}}' \"\${CID}\"); - if ! CRM_MSG=\$(docker container rm \${CID} 2>&1); then - log ERROR \"Failed to remove \${STATUS} container \${CNAME}, which is using image \${IMAGE}. \$(echo \${CRM_MSG})\"; - continue; - fi - log INFO \"Removed \${STATUS} container \${CNAME}. It was using image \${IMAGE}.\"; - done; - }; - for IMAGE in \${IMAGES_TO_REMOVE}; do - if ! docker image inspect \${IMAGE} 1>/dev/null 2>&1 ; then - log DEBUG \"There is no image \${IMAGE} on the node.\"; - continue; - fi; - remove_container \${IMAGE} exited; - remove_container \${IMAGE} dead; - if ! RMI_MSG=\$(docker rmi \${IMAGE} 2>&1); then - log ERROR \"Failed to remove image \${IMAGE}. \$(echo \${RMI_MSG})\"; - continue; - fi; - log INFO \"Removed image \${IMAGE}.\"; - done; - log INFO \"Done.\"; - " + --env "GANTRY_IMAGES_TO_REMOVE=$(echo "${STATIC_VAR_IMAGES_TO_REMOVE}" | tr '\n' ' ')" \ + "${IMAGE_OF_THIS_CONTAINER}" wait_service_state "${SERVICE_NAME}" --complete; docker_service_logs "${SERVICE_NAME}" docker_service_remove "${SERVICE_NAME}" @@ -247,6 +235,7 @@ in_list() { } current_container_name() { + [ -n "${STATIC_VAR_CURRENT_CONTAINER_NAME}" ] && echo "${STATIC_VAR_CURRENT_CONTAINER_NAME}" && return 0 local ALL_NETWORKS GWBRIDGE_NETWORK IPS; ALL_NETWORKS=$(docker network ls --format '{{.ID}}') || return 1; [ -z "${ALL_NETWORKS}" ] && return 0; @@ -264,6 +253,7 @@ current_container_name() { echo "${NAME_AND_IP}" | grep -q "${IP}" || continue; local NAME; NAME=$(echo "${NAME_AND_IP}" | sed "s/\(.*\)=${IP}.*$/\1/"); + STATIC_VAR_CURRENT_CONTAINER_NAME=${NAME} echo "${NAME}"; return 0; done; @@ -273,10 +263,12 @@ current_container_name() { } current_service_name() { + [ -n "${STATIC_VAR_CURRENT_SERVICE_NAME}" ] && echo "${STATIC_VAR_CURRENT_SERVICE_NAME}" && return 0 local CNAME CNAME=$(current_container_name) || return 1 [ -z "${CNAME}" ] && return 0 SNAME=$(docker container inspect "${CNAME}" --format '{{range $key,$value := .Config.Labels}}{{$key}}={{println $value}}{{end}}' | grep "com.docker.swarm.service.name" | sed "s/com.docker.swarm.service.name=\(.*\)$/\1/") || return 1 + STATIC_VAR_CURRENT_SERVICE_NAME=${SNAME} echo "${SNAME}" } @@ -301,6 +293,18 @@ get_service_mode() { echo "${MODE}" } +get_service_image() { + local SERVICE_NAME="${1}" + local IMAGE_WITH_DIGEST= + docker service inspect -f '{{.Spec.TaskTemplate.ContainerSpec.Image}}' "${SERVICE_NAME}" +} + +get_service_previous_image() { + local SERVICE_NAME="${1}" + local IMAGE_WITH_DIGEST= + docker service inspect -f '{{.PreviousSpec.TaskTemplate.ContainerSpec.Image}}' "${SERVICE_NAME}" +} + # echo the mode when the service is replicated job or global job # return whether a service is replicated job or global job service_is_job() { @@ -363,7 +367,7 @@ inspect_image() { local SERVICE_NAME="${1}" local DOCKER_CONFIG="${2}" local IMAGE_WITH_DIGEST= - if ! IMAGE_WITH_DIGEST=$(docker service inspect -f '{{.Spec.TaskTemplate.ContainerSpec.Image}}' "${SERVICE_NAME}" 2>&1); then + if ! IMAGE_WITH_DIGEST=$(get_service_image "${SERVICE_NAME}" 2>&1); then log ERROR "Failed to obtain image from service ${SERVICE_NAME}. ${IMAGE_WITH_DIGEST}" return 1 fi @@ -497,8 +501,8 @@ update_single_service() { fi local PREVIOUS_IMAGE= local CURRENT_IMAGE= - PREVIOUS_IMAGE=$(docker service inspect -f '{{.PreviousSpec.TaskTemplate.ContainerSpec.Image}}' "${SERVICE_NAME}") - CURRENT_IMAGE=$(docker service inspect -f '{{.Spec.TaskTemplate.ContainerSpec.Image}}' "${SERVICE_NAME}") + PREVIOUS_IMAGE=$(get_service_previous_image "${SERVICE_NAME}") + CURRENT_IMAGE=$(get_service_image "${SERVICE_NAME}") if [ "${PREVIOUS_IMAGE}" = "${CURRENT_IMAGE}" ]; then log INFO "No updates." return 0