mirror of
https://github.com/project-zot/zot.git
synced 2026-06-17 04:48:26 +08:00
refactor(sync): use task scheduler (#1301)
Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
This commit is contained in:
@@ -39,17 +39,33 @@ function zot_stop() {
|
||||
pkill zot
|
||||
}
|
||||
|
||||
function wait_str() {
|
||||
local filepath="$1"
|
||||
local search_term="$2"
|
||||
local wait_time="${3:-2m}"
|
||||
|
||||
(timeout $wait_time tail -F -n0 "$filepath" &) | grep -q "$search_term" && return 0
|
||||
|
||||
echo "timeout of $wait_time reached. unable to find '$search_term' in '$filepath'"
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
function wait_for_string() {
|
||||
string=$1
|
||||
filepath=$2
|
||||
local search_term="$1"
|
||||
local filepath="$2"
|
||||
local wait_time="${3:-2m}"
|
||||
|
||||
while [ ! -f $filepath ]
|
||||
do sleep 2;
|
||||
done
|
||||
wait_file "$filepath" 60 || { echo "server log file missing: '$filepath'"; return 1; }
|
||||
|
||||
while ! grep "${string}" $filepath
|
||||
do sleep 10;
|
||||
done
|
||||
wait_str "$filepath" "$search_term" "$wait_time"
|
||||
}
|
||||
|
||||
function wait_file() {
|
||||
local file="$1"; shift
|
||||
local wait_seconds="${1:-60}"; shift
|
||||
|
||||
until test $((wait_seconds--)) -eq 0 -o -f "$file" ; do sleep 1; done
|
||||
}
|
||||
|
||||
function wait_zot_reachable() {
|
||||
|
||||
@@ -3,7 +3,9 @@ TEST_DATA_DIR=${ROOT_DIR}/test/data/
|
||||
OS="${OS:-linux}"
|
||||
ARCH="${ARCH:-amd64}"
|
||||
ZOT_PATH=${ROOT_DIR}/bin/zot-${OS}-${ARCH}
|
||||
|
||||
ZOT_MINIMAL_PATH=${ROOT_DIR}/bin/zot-${OS}-${ARCH}-minimal
|
||||
ZB_PATH=${ROOT_DIR}/bin/zb-${OS}-${ARCH}
|
||||
|
||||
mkdir -p ${TEST_DATA_DIR}
|
||||
|
||||
@@ -18,6 +20,11 @@ function verify_prerequisites {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ ! -f ${ZB_PATH} ]; then
|
||||
echo "you need to build ${ZB_PATH} before running the tests" >&3
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ ! -f ${ZOT_MINIMAL_PATH} ]; then
|
||||
echo "you need to build ${ZOT_MINIMAL_PATH} before running tests" >&3
|
||||
return 1
|
||||
@@ -45,9 +52,44 @@ function zot_serve() {
|
||||
local config_file=${2}
|
||||
local pid_dir=${3}
|
||||
${zot_path} serve ${config_file} &
|
||||
|
||||
echo $! >>${pid_dir}/zot.pid
|
||||
}
|
||||
|
||||
function zb_run() {
|
||||
local zot_address=${1}
|
||||
${ZB_PATH} -c 10 -n 100 -o stdout ${zot_address} --skip-cleanup
|
||||
}
|
||||
|
||||
function wait_str() {
|
||||
local filepath="$1"
|
||||
local search_term="$2"
|
||||
local wait_time="${3:-2m}"
|
||||
|
||||
(timeout $wait_time tail -F -n0 "$filepath" &) | grep -q "$search_term" && return 0
|
||||
|
||||
echo "timeout of $wait_time reached. unable to find '$search_term' in '$filepath'"
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
function wait_for_string() {
|
||||
local search_term="$1"
|
||||
local filepath="$2"
|
||||
local wait_time="${3:-2m}"
|
||||
|
||||
wait_file "$filepath" 60 || { echo "server log file missing: '$filepath'"; return 1; }
|
||||
|
||||
wait_str "$filepath" "$search_term" "$wait_time"
|
||||
}
|
||||
|
||||
function wait_file() {
|
||||
local file="$1"; shift
|
||||
local wait_seconds="${1:-60}"; shift
|
||||
|
||||
until test $((wait_seconds--)) -eq 0 -o -f "$file" ; do sleep 1; done
|
||||
}
|
||||
|
||||
function zot_stop() {
|
||||
local pid_dir=${1}
|
||||
cat ${pid_dir}/zot.pid
|
||||
|
||||
@@ -223,7 +223,7 @@ function teardown_file() {
|
||||
# attach signature
|
||||
echo "{\"artifact\": \"\", \"signature\": \"pat hancock\"}" > signature.json
|
||||
start=`date +%s`
|
||||
run oras attach --plain-http 127.0.0.1:8080/golang:1.20 --artifact-type 'signature/example' ./signature.json:application/json
|
||||
run oras attach --plain-http 127.0.0.1:8080/golang:1.20 --image-spec v1.1-image --artifact-type 'signature/example' ./signature.json:application/json
|
||||
[ "$status" -eq 0 ]
|
||||
end=`date +%s`
|
||||
runtime=$((end-start))
|
||||
@@ -232,7 +232,7 @@ function teardown_file() {
|
||||
# attach sbom
|
||||
echo "{\"version\": \"0.0.0.0\", \"artifact\": \"'127.0.0.1:8080/golang:1.20'\", \"contents\": \"good\"}" > sbom.json
|
||||
start=`date +%s`
|
||||
run oras attach --plain-http 127.0.0.1:8080/golang:1.20 --artifact-type 'sbom/example' ./sbom.json:application/json
|
||||
run oras attach --plain-http 127.0.0.1:8080/golang:1.20 --image-spec v1.1-image --artifact-type 'sbom/example' ./sbom.json:application/json
|
||||
[ "$status" -eq 0 ]
|
||||
end=`date +%s`
|
||||
runtime=$((end-start))
|
||||
|
||||
@@ -113,7 +113,9 @@ function teardown_file() {
|
||||
wait_zot_reachable "http://127.0.0.1:8080/v2/"
|
||||
start=`date +%s`
|
||||
echo "waiting for restoring blobs task to finish" >&3
|
||||
wait_for_string "dedupe rebuild: finished" ${ZOT_LOG_FILE}
|
||||
run wait_for_string "dedupe rebuild: finished" ${ZOT_LOG_FILE} "5m"
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
end=`date +%s`
|
||||
|
||||
runtime=$((end-start))
|
||||
|
||||
@@ -46,7 +46,7 @@ function setup_file() {
|
||||
],
|
||||
"onDemand": false,
|
||||
"tlsVerify": false,
|
||||
"PollInterval": "5s",
|
||||
"PollInterval": "1s",
|
||||
"content": [
|
||||
{
|
||||
"prefix": "**"
|
||||
@@ -282,7 +282,7 @@ EOF
|
||||
|
||||
@test "sync signatures periodically" {
|
||||
# wait for signatures to be copied
|
||||
run sleep 5s
|
||||
run sleep 15s
|
||||
|
||||
run notation verify --plain-http localhost:8081/golang:1.20
|
||||
[ "$status" -eq 0 ]
|
||||
@@ -312,7 +312,7 @@ EOF
|
||||
|
||||
@test "sync oras artifact periodically" {
|
||||
# # wait for oras artifact to be copied
|
||||
run sleep 5s
|
||||
run sleep 15s
|
||||
run oras pull --plain-http 127.0.0.1:8081/hello-artifact:v2 -d -v
|
||||
[ "$status" -eq 0 ]
|
||||
grep -q "hello world" artifact.txt
|
||||
@@ -337,7 +337,7 @@ EOF
|
||||
|
||||
@test "sync helm chart periodically" {
|
||||
# wait for helm chart to be copied
|
||||
run sleep 5s
|
||||
run sleep 15s
|
||||
|
||||
local chart_version=$(awk '/version/{printf $2}' ${BATS_FILE_TMPDIR}/helm-charts/charts/zot/Chart.yaml)
|
||||
run helm pull oci://localhost:8081/zot-chart/zot --version ${chart_version}
|
||||
@@ -364,7 +364,7 @@ EOF
|
||||
|
||||
@test "sync OCI artifact (oci image mediatype) periodically" {
|
||||
# wait for helm chart to be copied
|
||||
run sleep 5s
|
||||
run sleep 15s
|
||||
run regctl manifest get localhost:8081/artifact:demo
|
||||
[ "$status" -eq 0 ]
|
||||
run regctl artifact get localhost:8081/artifact:demo
|
||||
@@ -389,7 +389,7 @@ EOF
|
||||
|
||||
@test "sync OCI artifact (oci artifact mediatype) periodically" {
|
||||
# wait for helm chart to be copied
|
||||
run sleep 5s
|
||||
run sleep 15s
|
||||
run regctl manifest get localhost:8081/newartifact:demo
|
||||
[ "$status" -eq 0 ]
|
||||
run regctl artifact get localhost:8081/newartifact:demo
|
||||
@@ -433,7 +433,7 @@ EOF
|
||||
|
||||
@test "sync OCI artifact references periodically" {
|
||||
# wait for OCI artifacts to be copied
|
||||
run sleep 5
|
||||
run sleep 20
|
||||
run regctl artifact get localhost:8081/manifest-ref:demo
|
||||
[ "$status" -eq 0 ]
|
||||
[ "${lines[-1]}" == "test artifact" ]
|
||||
|
||||
+100
-13
@@ -23,19 +23,79 @@ function setup_file() {
|
||||
"port": "8090"
|
||||
},
|
||||
"log": {
|
||||
"level": "debug"
|
||||
"level": "debug",
|
||||
"output": "/tmp/blackbox.log"
|
||||
},
|
||||
"extensions": {
|
||||
"sync": {
|
||||
"registries": [
|
||||
{
|
||||
"urls": [
|
||||
"https://docker.io/library",
|
||||
"https://registry.k8s.io",
|
||||
"https://aws.amazon.com/ecr",
|
||||
"https://gcr.io",
|
||||
"https://docker.io/library"
|
||||
],
|
||||
"content": [
|
||||
{
|
||||
"prefix": "registry"
|
||||
},
|
||||
{
|
||||
"prefix": "archlinux"
|
||||
}
|
||||
],
|
||||
"onDemand": true,
|
||||
"tlsVerify": true
|
||||
},
|
||||
{
|
||||
"urls": [
|
||||
"https://registry.k8s.io"
|
||||
],
|
||||
"content": [
|
||||
{
|
||||
"prefix": "kube-apiserver"
|
||||
},
|
||||
{
|
||||
"prefix": "pause"
|
||||
},
|
||||
{
|
||||
"prefix": "kube-apiserver-amd64"
|
||||
}
|
||||
],
|
||||
"onDemand": true,
|
||||
"tlsVerify": true
|
||||
},
|
||||
{
|
||||
"urls": [
|
||||
"https://public.ecr.aws"
|
||||
],
|
||||
"content": [
|
||||
{
|
||||
"prefix": "amazonlinux/amazonlinux"
|
||||
}
|
||||
],
|
||||
"onDemand": true,
|
||||
"tlsVerify": true
|
||||
},
|
||||
{
|
||||
"urls": [
|
||||
"https://gcr.io"
|
||||
|
||||
],
|
||||
"content": [
|
||||
{
|
||||
"prefix": "google-containers/kube-proxy-amd64"
|
||||
}
|
||||
],
|
||||
"onDemand": true,
|
||||
"tlsVerify": true
|
||||
},
|
||||
{
|
||||
"urls": [
|
||||
"https://mcr.microsoft.com"
|
||||
],
|
||||
"content": [
|
||||
{
|
||||
"prefix": "azure-cognitive-services/vision/spatial-analysis/diagnostics"
|
||||
}
|
||||
],
|
||||
"onDemand": true,
|
||||
"tlsVerify": true
|
||||
}
|
||||
@@ -80,7 +140,35 @@ function teardown_file() {
|
||||
run curl http://127.0.0.1:8090/v2/_catalog
|
||||
[ "$status" -eq 0 ]
|
||||
[ $(echo "${lines[-1]}" | jq '.repositories[0]') = '"archlinux"' ]
|
||||
run curl http://127.0.0.1:8090/v2/registry/tags/list
|
||||
run curl http://127.0.0.1:8090/v2/archlinux/tags/list
|
||||
[ "$status" -eq 0 ]
|
||||
[ $(echo "${lines[-1]}" | jq '.tags[]') = '"latest"' ]
|
||||
}
|
||||
|
||||
@test "sync k8s image list on demand" {
|
||||
run skopeo --insecure-policy copy --multi-arch=all --src-tls-verify=false \
|
||||
docker://127.0.0.1:8090/kube-apiserver:v1.26.0 \
|
||||
oci:${TEST_DATA_DIR}
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
run curl http://127.0.0.1:8090/v2/_catalog
|
||||
[ "$status" -eq 0 ]
|
||||
[ $(echo "${lines[-1]}" | jq '.repositories[1]') = '"kube-apiserver"' ]
|
||||
run curl http://127.0.0.1:8090/v2/kube-apiserver/tags/list
|
||||
[ "$status" -eq 0 ]
|
||||
[ $(echo "${lines[-1]}" | jq '.tags[]') = '"v1.26.0"' ]
|
||||
}
|
||||
|
||||
@test "sync k8s image on demand" {
|
||||
run skopeo --insecure-policy copy --src-tls-verify=false \
|
||||
docker://127.0.0.1:8090/pause \
|
||||
oci:${TEST_DATA_DIR}
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
run curl http://127.0.0.1:8090/v2/_catalog
|
||||
[ "$status" -eq 0 ]
|
||||
[ $(echo "${lines[-1]}" | jq '.repositories[2]') = '"pause"' ]
|
||||
run curl http://127.0.0.1:8090/v2/pause/tags/list
|
||||
[ "$status" -eq 0 ]
|
||||
[ $(echo "${lines[-1]}" | jq '.tags[]') = '"latest"' ]
|
||||
}
|
||||
@@ -98,13 +186,13 @@ function teardown_file() {
|
||||
}
|
||||
|
||||
@test "sync image on demand from aws.amazon.com/ecr" {
|
||||
run skopeo copy docker://127.0.0.1:8090/amazonlinux:latest oci:${TEST_DATA_DIR} --src-tls-verify=false
|
||||
run skopeo copy docker://127.0.0.1:8090/amazonlinux/amazonlinux:latest oci:${TEST_DATA_DIR} --src-tls-verify=false
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
run curl http://127.0.0.1:8090/v2/_catalog
|
||||
[ "$status" -eq 0 ]
|
||||
[ $(echo "${lines[-1]}"| jq '.repositories | map(select(. == "amazonlinux"))' | jq '.[]') = '"amazonlinux"' ]
|
||||
run curl http://127.0.0.1:8090/v2/amazonlinux/tags/list
|
||||
[ $(echo "${lines[-1]}"| jq '.repositories | map(select(. == "amazonlinux/amazonlinux"))' | jq '.[]') = '"amazonlinux/amazonlinux"' ]
|
||||
run curl http://127.0.0.1:8090/v2/amazonlinux/amazonlinux/tags/list
|
||||
[ "$status" -eq 0 ]
|
||||
[ $(echo "${lines[-1]}" | jq '.tags[]') = '"latest"' ]
|
||||
}
|
||||
@@ -166,13 +254,13 @@ function teardown_file() {
|
||||
}
|
||||
|
||||
@test "run docker with image synced from aws.amazon.com/ecr" {
|
||||
run docker run -d 127.0.0.1:8090/amazonlinux:latest
|
||||
run docker run -d 127.0.0.1:8090/amazonlinux/amazonlinux:latest
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
run curl http://127.0.0.1:8090/v2/_catalog
|
||||
[ "$status" -eq 0 ]
|
||||
[ $(echo "${lines[-1]}"| jq '.repositories | map(select(. == "amazonlinux"))' | jq '.[]') = '"amazonlinux"' ]
|
||||
run curl http://127.0.0.1:8090/v2/amazonlinux/tags/list
|
||||
[ $(echo "${lines[-1]}"| jq '.repositories | map(select(. == "amazonlinux/amazonlinux"))' | jq '.[]') = '"amazonlinux/amazonlinux"' ]
|
||||
run curl http://127.0.0.1:8090/v2/amazonlinux/amazonlinux/tags/list
|
||||
[ "$status" -eq 0 ]
|
||||
[ $(echo "${lines[-1]}" | jq '.tags[]') = '"latest"' ]
|
||||
|
||||
@@ -206,4 +294,3 @@ function teardown_file() {
|
||||
|
||||
run docker kill $(docker ps -q)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
load helpers_sync
|
||||
|
||||
function setup_file() {
|
||||
# Verify prerequisites are available
|
||||
if ! verify_prerequisites; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Setup zot server
|
||||
local zot_sync_per_root_dir=${BATS_FILE_TMPDIR}/zot-per
|
||||
|
||||
local zot_sync_per_config_file=${BATS_FILE_TMPDIR}/zot_sync_per_config.json
|
||||
local zot_sync_ondemand_config_file=${BATS_FILE_TMPDIR}/zot_sync_ondemand_config.json
|
||||
|
||||
local zot_minimal_root_dir=${BATS_FILE_TMPDIR}/zot-minimal
|
||||
local zot_minimal_config_file=${BATS_FILE_TMPDIR}/zot_minimal_config.json
|
||||
|
||||
local oci_data_dir=${BATS_FILE_TMPDIR}/oci
|
||||
mkdir -p ${zot_sync_per_root_dir}
|
||||
mkdir -p ${zot_minimal_root_dir}
|
||||
mkdir -p ${oci_data_dir}
|
||||
|
||||
local ZOT_LOG_FILE=${zot_sync_per_root_dir}/zot.log
|
||||
|
||||
|
||||
cat >${zot_sync_per_config_file} <<EOF
|
||||
{
|
||||
"distSpecVersion": "1.1.0",
|
||||
"storage": {
|
||||
"rootDirectory": "${zot_sync_per_root_dir}"
|
||||
},
|
||||
"http": {
|
||||
"address": "0.0.0.0",
|
||||
"port": "8081"
|
||||
},
|
||||
"log": {
|
||||
"level": "debug",
|
||||
"output": "${ZOT_LOG_FILE}"
|
||||
},
|
||||
"extensions": {
|
||||
"sync": {
|
||||
"registries": [
|
||||
{
|
||||
"urls": [
|
||||
"http://localhost:8080"
|
||||
],
|
||||
"onDemand": false,
|
||||
"tlsVerify": false,
|
||||
"PollInterval": "5m",
|
||||
"content": [
|
||||
{
|
||||
"prefix": "**"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
cat >${zot_minimal_config_file} <<EOF
|
||||
{
|
||||
"distSpecVersion": "1.1.0",
|
||||
"storage": {
|
||||
"rootDirectory": "${zot_minimal_root_dir}"
|
||||
},
|
||||
"http": {
|
||||
"address": "0.0.0.0",
|
||||
"port": "8080"
|
||||
},
|
||||
"log": {
|
||||
"level": "debug",
|
||||
"output": "${zot_minimal_root_dir}/zot.log"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
setup_zot_minimal_file_level ${zot_minimal_config_file}
|
||||
wait_zot_reachable "http://127.0.0.1:8080/v2/_catalog"
|
||||
}
|
||||
|
||||
function teardown_file() {
|
||||
local zot_sync_per_root_dir=${BATS_FILE_TMPDIR}/zot-per
|
||||
local oci_data_dir=${BATS_FILE_TMPDIR}/oci
|
||||
local zot_minimal_root_dir=${BATS_FILE_TMPDIR}/zot-minimal
|
||||
teardown_zot_file_level
|
||||
rm -rf ${zot_sync_per_root_dir}
|
||||
rm -rf ${zot_minimal_root_dir}
|
||||
rm -rf ${oci_data_dir}
|
||||
}
|
||||
|
||||
# sync zb images
|
||||
@test "run zb benchmark and let zot sync all repos" {
|
||||
local zot_sync_per_root_dir=${BATS_FILE_TMPDIR}/zot-per
|
||||
local zot_sync_per_config_file=${BATS_FILE_TMPDIR}/zot_sync_per_config.json
|
||||
local zot_minimal_root_dir=${BATS_FILE_TMPDIR}/zot-minimal
|
||||
local ZOT_LOG_FILE=${zot_sync_per_root_dir}/zot.log
|
||||
|
||||
zb_run "http://127.0.0.1:8080"
|
||||
|
||||
# start zot sync server
|
||||
setup_zot_file_level ${zot_sync_per_config_file}
|
||||
wait_zot_reachable "http://127.0.0.1:8081/v2/_catalog"
|
||||
|
||||
start=`date +%s`
|
||||
echo "waiting for sync to finish" >&3
|
||||
|
||||
run wait_for_string "sync: finished syncing all repos" ${ZOT_LOG_FILE} "3m"
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
end=`date +%s`
|
||||
|
||||
runtime=$((end-start))
|
||||
echo "sync finished in $runtime sec" >&3
|
||||
sleep 10 # wait a bit more because sync runs in background.
|
||||
|
||||
# diff, but exclude log files, .sync subdirs and cache.db
|
||||
run diff -r -x "*.db" -x ".sync" -x "*.log" ${zot_sync_per_root_dir} ${zot_minimal_root_dir}
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
Reference in New Issue
Block a user