Skip to content

Commit b59d4af

Browse files
committed
lib/release: Add image validation
Here we add 'release::docker::validate_remote_manifests()', a function which validates the existence of image manifests on a remote registry by doing the following: - Using 'skopeo inspect' to retrieve an image manifest - Looping through the architectures and checking for an architecture-specific digest within the manifest using jq We do some minor cleanup by using directory wildcards instead of arrays to populate for loops. Additionally, we validate the correct amount of arguments for 'release::docker::validate_remote_manifests()' and 'release::docker::release()' using 'common::argc_validate'. This function closely resembles 'release::docker::release()' and could probably be consolidated. We make the decision to not do this refactor here to minimize the changes to surrounding functions. Signed-off-by: Stephen Augustus <saugustus@vmware.com>
1 parent 29b8e1d commit b59d4af

File tree

2 files changed

+97
-17
lines changed

2 files changed

+97
-17
lines changed

anago

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,10 +1454,8 @@ push_all_artifacts () {
14541454
$KUBE_DOCKER_REGISTRY $version $BUILD_OUTPUT-$version || return 1
14551455
fi
14561456

1457-
# TODO(vdf): Add image manifest validation logic
1458-
# Maybe consider adding this to release::docker::release
1459-
# and renaming that function.
1460-
logecho "Validating image manifests (# TODO(vdf): currently a no-op)..." || return 1
1457+
common::runstep release::docker::validate_remote_manifests \
1458+
$KUBE_DOCKER_REGISTRY $version $BUILD_OUTPUT-$version || return 1
14611459

14621460
common::runstep release::gcs::publish_version \
14631461
$BUCKET_TYPE $version $BUILD_OUTPUT-$version $RELEASE_BUCKET || return 1

lib/releaselib.sh

Lines changed: 95 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ readonly CI_BUCKET="kubernetes-release-dev"
3131

3232
# TODO(vdf): Need to reference K8s Infra registries here
3333
readonly GCRIO_PATH_PROD="k8s.gcr.io"
34+
# TODO(vdf): Remove all GCRIO_PATH_PROD_PUSH logic once the k8s.gcr.io vanity
35+
# domain flip (VDF) is successful
3436
readonly GCRIO_PATH_PROD_PUSH="gcr.io/google-containers"
3537
readonly GCRIO_PATH_TEST="gcr.io/k8s-staging-kubernetes"
3638

@@ -650,7 +652,6 @@ release::gcs::locally_stage_release_artifacts() {
650652
# --release-kind used by push-build.sh
651653
local release_kind=${4:-"kubernetes"}
652654
local platform
653-
local platforms
654655
local release_stage=$build_output/release-stage
655656
local release_tars=$build_output/release-tars
656657
local gcs_stage=$build_output/gcs-stage/$version
@@ -745,8 +746,7 @@ release::gcs::locally_stage_release_artifacts() {
745746

746747
# Upload the "naked" binaries to GCS. This is useful for install scripts that
747748
# download the binaries directly and don't need tars.
748-
platforms=($(cd "$release_stage/client"; echo *))
749-
for platform in "${platforms[@]}"; do
749+
for platform in ${release_stage}/client/*; do
750750
src="$release_stage/client/$platform/$release_kind/client/bin/*"
751751
dst="bin/${platform/-//}/"
752752
# We assume here the "server package" is a superset of the "client package"
@@ -1020,30 +1020,30 @@ release::gcs::publish () {
10201020
# @param build_output - build output directory
10211021
# @return 1 on failure
10221022
release::docker::release () {
1023-
local registry=$1
1024-
local push_registry=$registry
1025-
local version=$2
1026-
local build_output=$3
1027-
local release_images=$build_output/release-images
1028-
local docker_target
1023+
local registry="$1"
1024+
local push_registry="$registry"
1025+
local version="$2"
1026+
local build_output="$3"
1027+
local release_images="$build_output/release-images"
10291028
local arch
1030-
local -a arches
10311029
local tarfile
10321030
local orig_tag
1033-
local -a new_tags
10341031
local new_tag
10351032
local binary
10361033
local -A manifest_images
10371034

1035+
common::argc_validate 3
1036+
1037+
# TODO(vdf): Remove all GCRIO_PATH_PROD_PUSH logic once the k8s.gcr.io vanity
1038+
# domain flip (VDF) is successful
10381039
if [[ "$registry" == "$GCRIO_PATH_PROD" ]]; then
10391040
# Switch to the push alias if using the $GCRIO_PATH_PROD alias
10401041
push_registry="$GCRIO_PATH_PROD_PUSH"
10411042
fi
10421043

10431044
logecho "Send docker containers from release-images to $push_registry..."
10441045

1045-
arches=($(cd "$release_images"; echo *))
1046-
for arch in ${arches[@]}; do
1046+
for arch in ${release_images}/*; do
10471047
for tarfile in $release_images/$arch/*.tar; do
10481048
# There may be multiple tags; just get the first
10491049
orig_tag=$(tar xf $tarfile manifest.json -O | jq -r '.[0].RepoTags[0]')
@@ -1099,6 +1099,88 @@ release::docker::release () {
10991099
return 0
11001100
}
11011101

1102+
# TODO(vdf): Consider collapsing this into release::docker::release and renaming
1103+
# that function AFTER the k8s.gcr.io Vanity Domain Flip (VDF).
1104+
###############################################################################
1105+
# Validates that image manifests have been pushed to a specified remote registry.
1106+
# Uses 'skopeo inspect'.
1107+
#
1108+
# @param registry - docker registry
1109+
# @param version - version tag
1110+
# @param build_output - build output directory
1111+
# @return 1 on failure
1112+
release::docker::validate_remote_manifests () {
1113+
local registry="$1"
1114+
local push_registry="$registry"
1115+
local version="$2"
1116+
local build_output="$3"
1117+
local release_images="$build_output/release-images"
1118+
local arch
1119+
local tarfile
1120+
local orig_tag
1121+
local new_tag
1122+
local binary
1123+
local -A manifest_images
1124+
1125+
common::argc_validate 3
1126+
1127+
# TODO(vdf): Remove all GCRIO_PATH_PROD_PUSH logic once the k8s.gcr.io vanity
1128+
# domain flip (VDF) is successful
1129+
if [[ "$registry" == "$GCRIO_PATH_PROD" ]]; then
1130+
# Switch to the push alias if using the $GCRIO_PATH_PROD alias
1131+
push_registry="$GCRIO_PATH_PROD_PUSH"
1132+
fi
1133+
1134+
logecho "Validating image manifests in $push_registry..."
1135+
1136+
for arch in ${release_images}/*; do
1137+
for tarfile in $release_images/$arch/*.tar; do
1138+
# There may be multiple tags; just get the first
1139+
orig_tag=$(tar xf $tarfile manifest.json -O | jq -r '.[0].RepoTags[0]')
1140+
if [[ ! "$orig_tag" =~ ^.+/(.+):.+$ ]]; then
1141+
logecho "$FAILED: malformed tag in $tarfile:"
1142+
logecho $orig_tag
1143+
return 1
1144+
fi
1145+
binary=${BASH_REMATCH[1]}
1146+
1147+
new_tag="$push_registry/${binary/-$arch/}"
1148+
manifest_images["${new_tag}"]+=" $arch"
1149+
done
1150+
done
1151+
1152+
for image in "${!manifest_images[@]}"; do
1153+
local archs
1154+
local manifest
1155+
local digest
1156+
1157+
logecho "Validating manifest list exists for ${image}:${version}..."
1158+
1159+
archs=$(echo "${manifest_images[$image]}" | sed -e 's/^[[:space:]]*//')
1160+
1161+
if ! manifest=$(skopeo inspect "docker://${image}:${version}" --raw); then
1162+
logecho "Could not find manifest list for ${image}:${version}"
1163+
return 1
1164+
fi
1165+
1166+
for arch in ${archs}; do
1167+
logecho "Checking image digest for ${image} on ${arch} architecture..."
1168+
1169+
digest=$(echo -n "${manifest}" \
1170+
| jq --arg a "${arch}" -r '.manifests[] | select(.platform.architecture==$a)' \
1171+
| jq -r '.digest')
1172+
1173+
if [[ -n "$digest" ]]; then
1174+
logecho "Digest for ${image} on ${arch}: ${digest}"
1175+
else
1176+
logecho "Could not find the image digest for ${image} on ${arch}. Exiting..."
1177+
return 1
1178+
fi
1179+
done
1180+
done
1181+
1182+
return 0
1183+
}
11021184

11031185
###############################################################################
11041186
# Get the kubecross image version for a given release branch.

0 commit comments

Comments
 (0)