Feature(setup): add Docker image digest verification before container startup 46/141246/2
authorsourabh_sourabh <sourabh.sourabh@est.tech>
Fri, 6 Jun 2025 16:31:16 +0000 (17:31 +0100)
committerSourabh Sourabh <sourabh.sourabh@est.tech>
Thu, 12 Jun 2025 12:59:39 +0000 (12:59 +0000)
- Integrated image validation into setup.sh using
  verify-docker-image-digests.sh
- Pre-checks Docker image digests before running docker-compose
- Logs detailed pull diagnostics, fallback to local images if pull fails

Issue-ID: CPS-2837
Change-Id: Iec5fb12091dcac853031fa8d083c51792f240eb4
Signed-off-by: sourabh_sourabh <sourabh.sourabh@est.tech>
k6-tests/setup.sh
k6-tests/verify-docker-image-digests.sh [new file with mode: 0644]

index 6a233ce..92abb2a 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Copyright 2024-2025 OpenInfra Foundation Europe.
+# Copyright 2024-2025 OpenInfra Foundation Europe. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # limitations under the License.
 #
 
+# Load image check and logging functions
+source "$(dirname "$0")/verify-docker-image-digests.sh"
+
 testProfile=$1
 ENV_FILE="../docker-compose/env/${testProfile}.env"
 COMPOSE_FILE="../docker-compose/cps-base.yml"
 
+# Define images to pre-check (add more if needed)
+IMAGES_TO_CHECK=(
+  "nexus3.onap.org:10003/onap/dmi-stub:latest"
+)
+
+# Run the image checks before anything else
+check_images "${IMAGES_TO_CHECK[@]}"
+
 # Define a function to encapsulate docker-compose command
 compose() {
   docker-compose \
diff --git a/k6-tests/verify-docker-image-digests.sh b/k6-tests/verify-docker-image-digests.sh
new file mode 100644 (file)
index 0000000..618035c
--- /dev/null
@@ -0,0 +1,126 @@
+#!/bin/bash
+#
+# Copyright 2025 OpenInfra Foundation Europe. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Exit on error, undefined variable, or pipefail
+set -euo pipefail
+
+# List of Docker images to check - passed via environment or hardcoded
+IMAGES_TO_CHECK=("${IMAGES_TO_CHECK[@]:-}")
+
+# Directory to store digest files
+DIGEST_DIR="${WORKSPACE:-.}/image/digest"
+mkdir -p "$DIGEST_DIR"
+
+# Function to sanitize image names for filenames
+sanitize_image_name() {
+  local image="$1"
+  echo "$image" | sed 's/[:\/]/_/g'
+}
+
+# Function to retrieve the digest of a local image
+get_local_digest() {
+  local image="$1"
+  docker inspect --format='{{index .RepoDigests 0}}' "$image" 2>/dev/null || echo "none"
+}
+
+# Function to pull the latest image and retrieve its digest
+pull_image_and_get_digest() {
+  local image="$1"
+  local pull_output
+
+  # Capture pull output and error
+  if ! pull_output=$(docker pull "$image" 2>&1); then
+    echo "โ›” Failed to pull image: $image"
+    if echo "$pull_output" | grep -q "toomanyrequests:"; then
+      echo "   โ— Detected Docker Hub rate limit (toomanyrequests:)"
+    fi
+    echo "   โš ๏ธ  Possible reasons:"
+    echo "     - Network issues"
+    echo "     - Image does not exist"
+    echo "     - Docker Hub rate limit exceeded"
+    echo "   ๐Ÿ”„ Attempting to retrieve local digest (if available)..."
+    get_local_digest "$image"
+    return 1
+  fi
+
+  get_local_digest "$image"
+}
+
+# Main image validation logic
+check_images() {
+  echo
+  echo "๐Ÿ” Starting Docker image verification..."
+  echo "โฑ๏ธ  Started at   : $(date -u)"
+
+  for IMAGE in "${IMAGES_TO_CHECK[@]}"; do
+    echo -e "\n๐Ÿงช Verifying Docker image: $IMAGE"
+    echo "   ๐Ÿ•’ Timestamp: $(date -u)"
+
+    local SANITIZED_IMAGE_NAME
+    SANITIZED_IMAGE_NAME=$(sanitize_image_name "$IMAGE")
+    local DIGEST_FILE="$DIGEST_DIR/${SANITIZED_IMAGE_NAME}.digest"
+
+    local PREVIOUS_DIGEST="none"
+    if [[ -f "$DIGEST_FILE" ]]; then
+      PREVIOUS_DIGEST=$(<"$DIGEST_FILE")
+    fi
+
+    local NEW_DIGEST
+    if ! NEW_DIGEST=$(pull_image_and_get_digest "$IMAGE"); then
+      echo "   โš ๏ธ  Using local image (if available)."
+      continue
+    fi
+
+    if [[ "$PREVIOUS_DIGEST" != "$NEW_DIGEST" ]]; then
+      echo "โš ๏ธ  Digest changed for $IMAGE"
+      echo "   ๐Ÿ”– Previous digest: $PREVIOUS_DIGEST"
+      echo "   ๐Ÿ†• New digest     : $NEW_DIGEST"
+      echo "$NEW_DIGEST" > "$DIGEST_FILE"
+      log_image_info "$IMAGE"
+    else
+      echo "โœ… Image content is unchanged. Digest remains:"
+      echo "   ๐Ÿ”– $NEW_DIGEST"
+    fi
+  done
+
+  echo -e "\nโœ… Docker image verification completed for all specified images."
+  echo "๐Ÿ•’ Finished at: $(date -u)"
+}
+
+# Function: Display local metadata for an image
+# Function: Display detailed metadata for a local Docker image with styled output
+log_image_info() {
+  local IMAGE_NAME="$1"
+  echo "๐Ÿ–ผ๏ธ  Docker Image Metadata for: $IMAGE_NAME"
+
+  local IMAGE_ID CREATED SIZE DIGEST
+  IMAGE_ID=$(docker inspect --format='{{.Id}}' "$IMAGE_NAME" 2>/dev/null || echo "โ“ unknown")
+  CREATED=$(docker inspect --format='{{.Created}}' "$IMAGE_NAME" 2>/dev/null || echo "โ“ unknown")
+  SIZE=$(docker inspect --format='{{.Size}}' "$IMAGE_NAME" 2>/dev/null || echo "โ“ unknown")
+  DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "$IMAGE_NAME" 2>/dev/null || echo "โ“ unknown")
+
+  echo "  ๐Ÿ†” Image ID     : $IMAGE_ID"
+  echo "  ๐Ÿ“… Created      : $CREATED"
+
+  if [[ "$SIZE" != "โ“ unknown" && "$SIZE" =~ ^[0-9]+$ ]]; then
+    # Using awk to avoid bc dependency
+    SIZE_MB=$(awk "BEGIN { printf \"%.2f\", $SIZE/1024/1024 }")
+    echo "  ๐Ÿ“ฆ Size         : ${SIZE_MB} MB"
+  else
+    echo "  ๐Ÿ“ฆ Size         : โ“ unknown"
+  fi
+  echo "  ๐Ÿ”– Digest       : $DIGEST"
+}
\ No newline at end of file