zotregistry.dev/zot@v1.4.4-0.20240314164342-eec277e14d20/test/blackbox/sync_cloud.bats (about)

     1  # Note: Intended to be run as "make run-blackbox-tests" or "make run-blackbox-ci"
     2  #       Makefile target installs & checks all necessary tooling
     3  #       Extra tools that are not covered in Makefile target needs to be added in verify_prerequisites()
     4  
     5  load helpers_zot
     6  load helpers_wait
     7  
     8  
     9  function verify_prerequisites() {
    10      if [ ! $(command -v curl) ]; then
    11          echo "you need to install curl as a prerequisite to running the tests" >&3
    12          return 1
    13      fi
    14  
    15      if [ ! $(command -v jq) ]; then
    16          echo "you need to install jq as a prerequisite to running the tests" >&3
    17          return 1
    18      fi
    19  
    20      return 0
    21  }
    22  
    23  function setup_file() {
    24      export COSIGN_PASSWORD=""
    25      export COSIGN_OCI_EXPERIMENTAL=1
    26      export COSIGN_EXPERIMENTAL=1
    27  
    28      # Verify prerequisites are available
    29      if ! $(verify_prerequisites); then
    30          exit 1
    31      fi
    32  
    33      # Download test data to folder common for the entire suite, not just this file
    34      skopeo --insecure-policy copy --format=oci docker://ghcr.io/project-zot/golang:1.20 oci:${TEST_DATA_DIR}/golang:1.20
    35      # Setup zot server
    36      local zot_sync_per_root_dir=${BATS_FILE_TMPDIR}/zot-per
    37      local zot_sync_ondemand_root_dir=${BATS_FILE_TMPDIR}/zot-ondemand
    38  
    39      local zot_sync_per_config_file=${BATS_FILE_TMPDIR}/zot_sync_per_config.json
    40      local zot_sync_ondemand_config_file=${BATS_FILE_TMPDIR}/zot_sync_ondemand_config.json
    41  
    42      local zot_minimal_root_dir=${BATS_FILE_TMPDIR}/zot-minimal
    43      local zot_minimal_config_file=${BATS_FILE_TMPDIR}/zot_minimal_config.json
    44  
    45      local oci_data_dir=${BATS_FILE_TMPDIR}/oci
    46      mkdir -p ${zot_sync_per_root_dir}
    47      mkdir -p ${zot_sync_ondemand_root_dir}
    48      mkdir -p ${zot_minimal_root_dir}
    49      mkdir -p ${oci_data_dir}
    50      zot_port1=$(get_free_port)
    51      echo ${zot_port1} > ${BATS_FILE_TMPDIR}/zot.port1
    52      zot_port2=$(get_free_port)
    53      echo ${zot_port2} > ${BATS_FILE_TMPDIR}/zot.port2
    54      zot_port3=$(get_free_port)
    55      echo ${zot_port3} > ${BATS_FILE_TMPDIR}/zot.port3
    56  
    57      cat >${zot_sync_per_config_file} <<EOF
    58  {
    59      "distSpecVersion": "1.1.0",
    60      "storage": {
    61          "rootDirectory": "${zot_sync_per_root_dir}",
    62          "dedupe": false,
    63          "remoteCache": false,
    64          "storageDriver": {
    65              "name": "s3",
    66              "rootdirectory": "/zot/per",
    67              "region": "us-east-2",
    68              "regionendpoint": "localhost:4566",
    69              "bucket": "zot-storage",
    70              "secure": false,
    71              "skipverify": true
    72          }
    73      },
    74      "http": {
    75          "address": "0.0.0.0",
    76          "port": "${zot_port1}"
    77      },
    78      "log": {
    79          "level": "debug"
    80      },
    81      "extensions": {
    82          "sync": {
    83              "downloadDir": "${zot_sync_per_root_dir}",
    84              "registries": [
    85                  {
    86                      "urls": [
    87                          "http://localhost:${zot_port3}"
    88                      ],
    89                      "onDemand": false,
    90                      "tlsVerify": false,
    91                      "PollInterval": "10s",
    92                      "content": [
    93                          {
    94                              "prefix": "**"
    95                          }
    96                      ]
    97                  }
    98              ]
    99          }
   100      }
   101  }
   102  EOF
   103  
   104      cat >${zot_sync_ondemand_config_file} <<EOF
   105  {
   106      "distSpecVersion": "1.1.0",
   107      "storage": {
   108          "rootDirectory": "${zot_sync_ondemand_root_dir}",
   109          "dedupe": false,
   110          "remoteCache": false,
   111          "storageDriver": {
   112              "name": "s3",
   113              "rootdirectory": "/zot/ondemand",
   114              "region": "us-east-2",
   115              "regionendpoint": "localhost:4566",
   116              "bucket": "zot-storage",
   117              "secure": false,
   118              "skipverify": true
   119          }
   120      },
   121      "http": {
   122          "address": "0.0.0.0",
   123          "port": "${zot_port2}"
   124      },
   125      "log": {
   126          "level": "debug"
   127      },
   128      "extensions": {
   129          "sync": {
   130              "downloadDir": "${zot_sync_ondemand_root_dir}",
   131              "registries": [
   132                  {
   133                      "urls": [
   134                          "http://localhost:${zot_port3}"
   135                      ],
   136                      "onDemand": true,
   137                      "tlsVerify": false,
   138                      "content": [
   139                          {
   140                              "prefix": "**"
   141                          }
   142                      ]
   143                  }
   144              ]
   145          }
   146      }
   147  }
   148  EOF
   149      cat >${zot_minimal_config_file} <<EOF
   150  {
   151      "distSpecVersion": "1.1.0",
   152      "storage": {
   153          "rootDirectory": "${zot_minimal_root_dir}"
   154      },
   155      "http": {
   156          "address": "0.0.0.0",
   157          "port": "${zot_port3}"
   158      },
   159      "log": {
   160          "level": "debug"
   161      }
   162  }
   163  EOF
   164      git -C ${BATS_FILE_TMPDIR} clone https://github.com/project-zot/helm-charts.git
   165  
   166      awslocal s3 --region "us-east-2" mb s3://zot-storage
   167  
   168      zot_serve ${ZOT_MINIMAL_PATH} ${zot_minimal_config_file}
   169      wait_zot_reachable ${zot_port3}
   170  
   171      zot_serve ${ZOT_PATH} ${zot_sync_per_config_file}
   172      wait_zot_reachable ${zot_port1}
   173  
   174      zot_serve ${ZOT_PATH} ${zot_sync_ondemand_config_file}
   175      wait_zot_reachable ${zot_port2}
   176  }
   177  
   178  function teardown_file() {
   179      zot_stop_all
   180      run rm -rf ${HOME}/.config/notation
   181      awslocal s3 rb s3://"zot-storage" --force
   182  }
   183  
   184  # sync image
   185  @test "sync golang image periodically" {
   186      zot_port1=`cat ${BATS_FILE_TMPDIR}/zot.port1`
   187      zot_port3=`cat ${BATS_FILE_TMPDIR}/zot.port3`
   188      run skopeo --insecure-policy copy --dest-tls-verify=false \
   189          oci:${TEST_DATA_DIR}/golang:1.20 \
   190          docker://127.0.0.1:${zot_port3}/golang:1.20
   191      [ "$status" -eq 0 ]
   192      run curl http://127.0.0.1:${zot_port3}/v2/_catalog
   193      [ "$status" -eq 0 ]
   194      [ $(echo "${lines[-1]}" | jq '.repositories[]') = '"golang"' ]
   195      run curl http://127.0.0.1:${zot_port1}/v2/_catalog
   196      run curl http://127.0.0.1:${zot_port3}/v2/golang/tags/list
   197      [ "$status" -eq 0 ]
   198      [ $(echo "${lines[-1]}" | jq '.tags[]') = '"1.20"' ]
   199  
   200      run sleep 30s
   201  
   202      run curl http://127.0.0.1:${zot_port1}/v2/_catalog
   203      [ "$status" -eq 0 ]
   204      [ $(echo "${lines[-1]}" | jq '.repositories[]') = '"golang"' ]
   205  
   206      run curl http://127.0.0.1:${zot_port1}/v2/golang/tags/list
   207      [ "$status" -eq 0 ]
   208      [ $(echo "${lines[-1]}" | jq '.tags[]') = '"1.20"' ]
   209  }
   210  
   211  @test "sync golang image ondemand" {
   212      zot_port2=`cat ${BATS_FILE_TMPDIR}/zot.port2`
   213      zot_port3=`cat ${BATS_FILE_TMPDIR}/zot.port3`
   214      run skopeo --insecure-policy copy --dest-tls-verify=false \
   215          oci:${TEST_DATA_DIR}/golang:1.20 \
   216          docker://127.0.0.1:${zot_port3}/golang:1.20
   217      [ "$status" -eq 0 ]
   218      run curl http://127.0.0.1:${zot_port3}/v2/_catalog
   219      [ "$status" -eq 0 ]
   220      [ $(echo "${lines[-1]}" | jq '.repositories[]') = '"golang"' ]
   221  
   222      # sync golang on demand
   223      run curl http://127.0.0.1:${zot_port2}/v2/golang/manifests/1.20
   224      [ "$status" -eq 0 ]
   225  
   226      run curl http://127.0.0.1:${zot_port3}/v2/golang/tags/list
   227      [ "$status" -eq 0 ]
   228      [ $(echo "${lines[-1]}" | jq '.tags[]') = '"1.20"' ]
   229  
   230      run curl http://127.0.0.1:${zot_port2}/v2/_catalog
   231      [ "$status" -eq 0 ]
   232      [ $(echo "${lines[-1]}" | jq '.repositories[]') = '"golang"' ]
   233  
   234      run curl http://127.0.0.1:${zot_port2}/v2/golang/tags/list
   235      [ "$status" -eq 0 ]
   236      [ $(echo "${lines[-1]}" | jq '.tags[]') = '"1.20"' ]
   237  }
   238  
   239  # sync index
   240  @test "sync image index periodically" {
   241      zot_port1=`cat ${BATS_FILE_TMPDIR}/zot.port1`
   242      zot_port3=`cat ${BATS_FILE_TMPDIR}/zot.port3`
   243      # --multi-arch below pushes an image index (containing many images) instead
   244      # of an image manifest (single image)
   245      run skopeo --insecure-policy copy --format=oci --dest-tls-verify=false --multi-arch=all \
   246          docker://public.ecr.aws/docker/library/busybox:latest \
   247          docker://127.0.0.1:${zot_port3}/busybox:latest
   248      [ "$status" -eq 0 ]
   249      run curl http://127.0.0.1:${zot_port3}/v2/_catalog
   250      [ "$status" -eq 0 ]
   251      [ $(echo "${lines[-1]}" | jq '.repositories[0]') = '"busybox"' ]
   252      run curl http://127.0.0.1:${zot_port3}/v2/busybox/tags/list
   253      [ "$status" -eq 0 ]
   254      [ $(echo "${lines[-1]}" | jq '.tags[]') = '"latest"' ]
   255  
   256      run sleep 30s
   257  
   258      run curl http://127.0.0.1:${zot_port1}/v2/_catalog
   259      [ "$status" -eq 0 ]
   260      [ $(echo "${lines[-1]}" | jq '.repositories[0]') = '"busybox"' ]
   261  
   262      run curl http://127.0.0.1:${zot_port1}/v2/busybox/tags/list
   263      [ "$status" -eq 0 ]
   264      [ $(echo "${lines[-1]}" | jq '.tags[]') = '"latest"' ]
   265  }
   266  
   267  @test "sync image index on demand" {
   268      zot_port2=`cat ${BATS_FILE_TMPDIR}/zot.port2`
   269      zot_port3=`cat ${BATS_FILE_TMPDIR}/zot.port3`
   270      # --multi-arch below pushes an image index (containing many images) instead
   271      # of an image manifest (single image)
   272      run skopeo --insecure-policy copy --format=oci --dest-tls-verify=false --multi-arch=all \
   273          docker://public.ecr.aws/docker/library/busybox:latest \
   274          docker://127.0.0.1:${zot_port3}/busybox:latest
   275      [ "$status" -eq 0 ]
   276      run curl http://127.0.0.1:${zot_port3}/v2/_catalog
   277      [ "$status" -eq 0 ]
   278      [ $(echo "${lines[-1]}" | jq '.repositories[1]') = '"golang"' ]
   279      run curl http://127.0.0.1:${zot_port3}/v2/busybox/tags/list
   280      [ "$status" -eq 0 ]
   281      [ $(echo "${lines[-1]}" | jq '.tags[]') = '"latest"' ]
   282  
   283      # sync busybox index on demand
   284      run curl http://127.0.0.1:${zot_port2}/v2/busybox/manifests/latest
   285      [ "$status" -eq 0 ]
   286  
   287      run curl http://127.0.0.1:${zot_port2}/v2/_catalog
   288      [ "$status" -eq 0 ]
   289      [ $(echo "${lines[-1]}" | jq '.repositories[1]') = '"golang"' ]
   290  
   291      run curl http://127.0.0.1:${zot_port2}/v2/busybox/tags/list
   292      [ "$status" -eq 0 ]
   293      [ $(echo "${lines[-1]}" | jq '.tags[]') = '"latest"' ]
   294  }
   295  
   296  # sign signatures
   297  @test "sign/verify with cosign" {
   298      zot_port3=`cat ${BATS_FILE_TMPDIR}/zot.port3`
   299      run cosign initialize
   300      [ "$status" -eq 0 ]
   301      run cosign generate-key-pair --output-key-prefix "${BATS_FILE_TMPDIR}/cosign-sign-sync-test"
   302      [ "$status" -eq 0 ]
   303      run cosign sign --key ${BATS_FILE_TMPDIR}/cosign-sign-sync-test.key localhost:${zot_port3}/golang:1.20 --yes
   304      [ "$status" -eq 0 ]
   305      run cosign sign --registry-referrers-mode=oci-1-1 --key ${BATS_FILE_TMPDIR}/cosign-sign-sync-test.key localhost:${zot_port3}/golang:1.20 --yes
   306      [ "$status" -eq 0 ]
   307      run cosign verify --key ${BATS_FILE_TMPDIR}/cosign-sign-sync-test.pub localhost:${zot_port3}/golang:1.20
   308      [ "$status" -eq 0 ]
   309  }
   310  
   311  @test "sign/verify with notation" {
   312      zot_port3=`cat ${BATS_FILE_TMPDIR}/zot.port3`
   313      run notation cert generate-test "notation-sign-sync-test"
   314      [ "$status" -eq 0 ]
   315  
   316      local trust_policy_file=${HOME}/.config/notation/trustpolicy.json
   317  
   318      cat >${trust_policy_file} <<EOF
   319  {
   320      "version": "1.0",
   321      "trustPolicies": [
   322          {
   323              "name": "notation-sign-sync-test",
   324              "registryScopes": [ "*" ],
   325              "signatureVerification": {
   326                  "level" : "strict"
   327              },
   328              "trustStores": [ "ca:notation-sign-sync-test" ],
   329              "trustedIdentities": [
   330                  "*"
   331              ]
   332          }
   333      ]
   334  }
   335  EOF
   336  
   337      run notation sign --key "notation-sign-sync-test" --insecure-registry localhost:${zot_port3}/golang:1.20
   338      [ "$status" -eq 0 ]
   339      run notation verify --insecure-registry localhost:${zot_port3}/golang:1.20
   340      [ "$status" -eq 0 ]
   341      run notation list --insecure-registry localhost:${zot_port3}/golang:1.20
   342      [ "$status" -eq 0 ]
   343  }
   344  
   345  @test "sync signatures periodically" {
   346      zot_port1=`cat ${BATS_FILE_TMPDIR}/zot.port1`
   347      # wait for signatures to be copied
   348      run sleep 15s
   349  
   350      run notation verify --insecure-registry localhost:${zot_port1}/golang:1.20
   351      [ "$status" -eq 0 ]
   352  
   353      run cosign verify --key ${BATS_FILE_TMPDIR}/cosign-sign-sync-test.pub localhost:${zot_port1}/golang:1.20
   354      [ "$status" -eq 0 ]
   355  }
   356  
   357  @test "sync signatures ondemand" {
   358      zot_port2=`cat ${BATS_FILE_TMPDIR}/zot.port2`
   359      run notation verify --insecure-registry localhost:${zot_port2}/golang:1.20
   360      [ "$status" -eq 0 ]
   361  
   362      run cosign verify --key ${BATS_FILE_TMPDIR}/cosign-sign-sync-test.pub localhost:${zot_port2}/golang:1.20
   363      [ "$status" -eq 0 ]
   364  }
   365  
   366  # sync oras artifacts
   367  @test "push oras artifact periodically" {
   368      zot_port3=`cat ${BATS_FILE_TMPDIR}/zot.port3`
   369      echo "{\"name\":\"foo\",\"value\":\"bar\"}" > config.json
   370      echo "hello world" > artifact.txt
   371      run oras push --plain-http 127.0.0.1:${zot_port3}/hello-artifact:v2 \
   372          --config config.json:application/vnd.acme.rocket.config.v1+json artifact.txt:text/plain -d -v
   373      [ "$status" -eq 0 ]
   374      rm -f artifact.txt
   375      rm -f config.json
   376  }
   377  
   378  @test "sync oras artifact periodically" {
   379      zot_port1=`cat ${BATS_FILE_TMPDIR}/zot.port1`
   380      # wait for oras artifact to be copied
   381      run sleep 15s
   382      run oras pull --plain-http 127.0.0.1:${zot_port1}/hello-artifact:v2 -d -v
   383      [ "$status" -eq 0 ]
   384      grep -q "hello world" artifact.txt
   385      rm -f artifact.txt
   386  }
   387  
   388  @test "sync oras artifact on demand" {
   389      zot_port2=`cat ${BATS_FILE_TMPDIR}/zot.port2`
   390      run oras pull --plain-http 127.0.0.1:${zot_port2}/hello-artifact:v2 -d -v
   391      [ "$status" -eq 0 ]
   392      grep -q "hello world" artifact.txt
   393      rm -f artifact.txt
   394  }
   395  
   396  # sync helm chart
   397  @test "push helm chart" {
   398      zot_port3=`cat ${BATS_FILE_TMPDIR}/zot.port3`
   399      run helm package ${BATS_FILE_TMPDIR}/helm-charts/charts/zot -d ${BATS_FILE_TMPDIR}
   400      [ "$status" -eq 0 ]
   401      local chart_version=$(awk '/version/{printf $2}' ${BATS_FILE_TMPDIR}/helm-charts/charts/zot/Chart.yaml)
   402      run helm push ${BATS_FILE_TMPDIR}/zot-${chart_version}.tgz oci://localhost:${zot_port3}/zot-chart
   403      [ "$status" -eq 0 ]
   404  }
   405  
   406  @test "sync helm chart periodically" {
   407      zot_port1=`cat ${BATS_FILE_TMPDIR}/zot.port1`
   408       # wait for helm chart to be copied
   409      run sleep 15s
   410  
   411      local chart_version=$(awk '/version/{printf $2}' ${BATS_FILE_TMPDIR}/helm-charts/charts/zot/Chart.yaml)
   412      run helm pull oci://localhost:${zot_port1}/zot-chart/zot --version ${chart_version} -d ${BATS_FILE_TMPDIR}
   413      [ "$status" -eq 0 ]
   414  }
   415  
   416  @test "sync helm chart on demand" {
   417      zot_port2=`cat ${BATS_FILE_TMPDIR}/zot.port2`
   418      local chart_version=$(awk '/version/{printf $2}' ${BATS_FILE_TMPDIR}/helm-charts/charts/zot/Chart.yaml)
   419      run helm pull oci://localhost:${zot_port2}/zot-chart/zot --version ${chart_version} -d ${BATS_FILE_TMPDIR}
   420      [ "$status" -eq 0 ]
   421  }
   422  
   423  # sync OCI artifacts
   424  @test "push OCI artifact (oci image mediatype) with regclient" {
   425      zot_port1=`cat ${BATS_FILE_TMPDIR}/zot.port1`
   426      zot_port2=`cat ${BATS_FILE_TMPDIR}/zot.port2`
   427      zot_port3=`cat ${BATS_FILE_TMPDIR}/zot.port3`
   428      run regctl registry set localhost:${zot_port3} --tls disabled
   429      run regctl registry set localhost:${zot_port1} --tls disabled
   430      run regctl registry set localhost:${zot_port2} --tls disabled
   431  
   432      run regctl artifact put localhost:${zot_port3}/artifact:demo <<EOF
   433  this is an oci image artifact
   434  EOF
   435      [ "$status" -eq 0 ]
   436  }
   437  
   438  @test "sync OCI artifact (oci image mediatype) periodically" {
   439      zot_port1=`cat ${BATS_FILE_TMPDIR}/zot.port1`
   440      # wait for helm chart to be copied
   441      run sleep 15s
   442      run regctl manifest get localhost:${zot_port1}/artifact:demo
   443      [ "$status" -eq 0 ]
   444      run regctl artifact get localhost:${zot_port1}/artifact:demo
   445      [ "$status" -eq 0 ]
   446      [ "${lines[-1]}" == "this is an oci image artifact" ]
   447  }
   448  
   449  @test "sync OCI artifact (oci image mediatype) on demand" {
   450      zot_port2=`cat ${BATS_FILE_TMPDIR}/zot.port2`
   451      run regctl manifest get localhost:${zot_port2}/artifact:demo
   452      [ "$status" -eq 0 ]
   453      run regctl artifact get localhost:${zot_port2}/artifact:demo
   454      [ "$status" -eq 0 ]
   455      [ "${lines[-1]}" == "this is an oci image artifact" ]
   456  }
   457  
   458  @test "push OCI artifact (oci artifact mediatype) with regclient" {
   459      zot_port3=`cat ${BATS_FILE_TMPDIR}/zot.port3`
   460      run regctl artifact put --artifact-type "application/vnd.example.icecream.v1"  localhost:${zot_port3}/newartifact:demo <<EOF
   461  this is an oci artifact
   462  EOF
   463      [ "$status" -eq 0 ]
   464  }
   465  
   466  @test "sync OCI artifact (oci artifact mediatype) periodically" {
   467      zot_port1=`cat ${BATS_FILE_TMPDIR}/zot.port1`
   468      # wait for helm chart to be copied
   469      run sleep 15s
   470      run regctl manifest get localhost:${zot_port1}/newartifact:demo
   471      [ "$status" -eq 0 ]
   472      run regctl artifact get localhost:${zot_port1}/newartifact:demo
   473      [ "$status" -eq 0 ]
   474      [ "${lines[-1]}" == "this is an oci artifact" ]
   475  }
   476  
   477  @test "sync OCI artifact (oci artifact mediatype) on demand" {
   478      zot_port2=`cat ${BATS_FILE_TMPDIR}/zot.port2`
   479      run regctl manifest get localhost:${zot_port2}/newartifact:demo
   480      [ "$status" -eq 0 ]
   481      run regctl artifact get localhost:${zot_port2}/newartifact:demo
   482      [ "$status" -eq 0 ]
   483      [ "${lines[-1]}" == "this is an oci artifact" ]
   484  }
   485  
   486  @test "push OCI artifact references with regclient" {
   487      zot_port3=`cat ${BATS_FILE_TMPDIR}/zot.port3`
   488      run regctl artifact put localhost:${zot_port3}/manifest-ref:demo <<EOF
   489  test artifact
   490  EOF
   491      [ "$status" -eq 0 ]
   492      run regctl artifact list localhost:${zot_port3}/manifest-ref:demo --format raw-body
   493      [ "$status" -eq 0 ]
   494      [ $(echo "${lines[-1]}" | jq '.manifests | length') -eq 0 ]
   495      run regctl artifact put --annotation  demo=true --annotation format=oci --artifact-type "application/vnd.example.icecream.v1" --subject localhost:${zot_port3}/manifest-ref:demo << EOF
   496  test reference
   497  EOF
   498      [ "$status" -eq 0 ]
   499      # with artifact media-type
   500      run regctl artifact put localhost:${zot_port3}/artifact-ref:demo <<EOF
   501  test artifact
   502  EOF
   503      [ "$status" -eq 0 ]
   504      run regctl artifact list localhost:${zot_port3}/artifact-ref:demo --format raw-body
   505      [ "$status" -eq 0 ]
   506      [ $(echo "${lines[-1]}" | jq '.manifests | length') -eq 0 ]
   507      run regctl artifact put --annotation  demo=true --annotation format=oci --artifact-type "application/vnd.example.icecream.v1" --subject localhost:${zot_port3}/artifact-ref:demo << EOF
   508  test reference
   509  EOF
   510      [ "$status" -eq 0 ]
   511  }
   512  
   513  @test "sync OCI artifact references periodically" {
   514      zot_port1=`cat ${BATS_FILE_TMPDIR}/zot.port1`
   515      # wait for OCI artifacts to be copied
   516      run sleep 20
   517      run regctl artifact get localhost:${zot_port1}/manifest-ref:demo
   518      [ "$status" -eq 0 ]
   519      [ "${lines[-1]}" == "test artifact" ]
   520      run regctl artifact list localhost:${zot_port1}/manifest-ref:demo --format raw-body
   521      [ "$status" -eq 0 ]
   522      [ $(echo "${lines[-1]}" | jq '.manifests | length') -eq 1 ]
   523      run regctl artifact list --filter-artifact-type "application/vnd.example.icecream.v1" localhost:${zot_port1}/manifest-ref:demo --format raw-body
   524      [ "$status" -eq 0 ]
   525      [ $(echo "${lines[-1]}" | jq '.manifests | length') -eq 1 ]
   526      run regctl artifact list --filter-artifact-type "application/invalid" localhost:${zot_port1}/manifest-ref:demo --format raw-body
   527      [ "$status" -eq 0 ]
   528      [ $(echo "${lines[-1]}" | jq '.manifests | length') -eq 0 ]
   529      # with artifact media-type
   530      run regctl artifact get localhost:${zot_port1}/artifact-ref:demo
   531      [ "$status" -eq 0 ]
   532      [ "${lines[-1]}" == "test artifact" ]
   533      run regctl artifact list localhost:${zot_port1}/artifact-ref:demo --format raw-body
   534      [ "$status" -eq 0 ]
   535      [ $(echo "${lines[-1]}" | jq '.manifests | length') -eq 1 ]
   536      run regctl artifact list --filter-artifact-type "application/vnd.example.icecream.v1" localhost:${zot_port1}/artifact-ref:demo --format raw-body
   537      [ "$status" -eq 0 ]
   538      [ $(echo "${lines[-1]}" | jq '.manifests | length') -eq 1 ]
   539      run regctl artifact list --filter-artifact-type "application/invalid" localhost:${zot_port1}/artifact-ref:demo --format raw-body
   540      [ "$status" -eq 0 ]
   541      [ $(echo "${lines[-1]}" | jq '.manifests | length') -eq 0 ]
   542  }
   543  
   544  @test "sync OCI artifact references on demand" {
   545      zot_port2=`cat ${BATS_FILE_TMPDIR}/zot.port2`
   546      run regctl artifact get localhost:${zot_port2}/manifest-ref:demo
   547      [ "$status" -eq 0 ]
   548      [ "${lines[-1]}" == "test artifact" ]
   549      run regctl artifact list localhost:${zot_port2}/manifest-ref:demo --format raw-body
   550      [ "$status" -eq 0 ]
   551      [ $(echo "${lines[-1]}" | jq '.manifests | length') -eq 1 ]
   552      run regctl artifact list --filter-artifact-type "application/vnd.example.icecream.v1" localhost:${zot_port2}/manifest-ref:demo --format raw-body
   553      [ "$status" -eq 0 ]
   554      [ $(echo "${lines[-1]}" | jq '.manifests | length') -eq 1 ]
   555      run regctl artifact list --filter-artifact-type "application/invalid" localhost:${zot_port2}/manifest-ref:demo --format raw-body
   556      [ "$status" -eq 0 ]
   557      [ $(echo "${lines[-1]}" | jq '.manifests | length') -eq 0 ]
   558      # with artifact media-type
   559      run regctl artifact get localhost:${zot_port2}/artifact-ref:demo
   560      [ "$status" -eq 0 ]
   561      [ "${lines[-1]}" == "test artifact" ]
   562      run regctl artifact list localhost:${zot_port2}/artifact-ref:demo --format raw-body
   563      [ "$status" -eq 0 ]
   564      [ $(echo "${lines[-1]}" | jq '.manifests | length') -eq 1 ]
   565      run regctl artifact list --filter-artifact-type "application/vnd.example.icecream.v1" localhost:${zot_port2}/artifact-ref:demo --format raw-body
   566      [ "$status" -eq 0 ]
   567      [ $(echo "${lines[-1]}" | jq '.manifests | length') -eq 1 ]
   568      run regctl artifact list --filter-artifact-type "application/invalid" localhost:${zot_port2}/artifact-ref:demo --format raw-body
   569      [ "$status" -eq 0 ]
   570      [ $(echo "${lines[-1]}" | jq '.manifests | length') -eq 0 ]
   571  }