Skip to content

Commit 5a2a8b2

Browse files
Fix cache digest comparison by using oras manifest fetch instead of client-side hash
get_image_digest computes a client-side sha256 of the raw manifest bytes from skopeo, which doesn't match the registry-assigned digest stored in the OpenShift ImageStream. Additionally, skopeo inspect without --raw fails entirely on ORAS artifacts. Replace with oras manifest fetch --descriptor which returns the registry-assigned digest, matching what oc import-image stores in the ImageStream. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7bfc2eb commit 5a2a8b2

2 files changed

Lines changed: 63 additions & 10 deletions

File tree

iib/workers/tasks/oras_utils.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# SPDX-License-Identifier: GPL-3.0-or-later
22
"""This file contains functions for ORAS (OCI Registry As Storage) operations."""
3+
import json
34
import logging
45
import os
56
import re
@@ -10,7 +11,7 @@
1011
from iib.common.tracing import instrument_tracing
1112
from iib.exceptions import IIBError
1213
from iib.workers.config import get_worker_config
13-
from iib.workers.tasks.utils import run_cmd, set_registry_auths, get_image_digest
14+
from iib.workers.tasks.utils import run_cmd, set_registry_auths, get_image_digest # noqa: F401
1415

1516
log = logging.getLogger(__name__)
1617

@@ -265,7 +266,16 @@ def verify_indexdb_cache_sync(tag: str) -> bool:
265266
registry=conf['iib_index_db_artifact_registry'], tag=tag
266267
)
267268

268-
quay_digest = get_image_digest(artifact_pullspec)
269+
oras_exclusive_auth_path = conf['iib_index_db_oras_auth_path']
270+
cmd_args = []
271+
if oras_exclusive_auth_path and os.path.exists(oras_exclusive_auth_path):
272+
cmd_args = ['--registry-config', oras_exclusive_auth_path]
273+
274+
descriptor = run_cmd(
275+
['oras', 'manifest', 'fetch', '--descriptor', *cmd_args, artifact_pullspec],
276+
exc_msg=f'Failed to fetch manifest descriptor for {artifact_pullspec}',
277+
)
278+
quay_digest = json.loads(descriptor)['digest']
269279
is_digest = get_image_stream_digest(tag)
270280

271281
return quay_digest == is_digest

tests/test_workers/test_tasks/test_oras_utils.py

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -432,44 +432,87 @@ def test_get_image_stream_digest_failure(mock_run_cmd):
432432

433433
@mock.patch('iib.workers.tasks.oras_utils.get_worker_config')
434434
@mock.patch('iib.workers.tasks.oras_utils.get_image_stream_digest')
435-
@mock.patch('iib.workers.tasks.oras_utils.get_image_digest')
436-
def test_verify_indexdb_cache_sync_match(mock_get_image_digest, mock_get_is_digest, mock_gwc):
435+
@mock.patch('iib.workers.tasks.oras_utils.run_cmd')
436+
def test_verify_indexdb_cache_sync_match(mock_run_cmd, mock_get_is_digest, mock_gwc):
437437
"""Test successful verification when digests match."""
438438
mock_gwc.return_value = {
439439
'iib_index_db_artifact_registry': 'test-artifact-registry',
440440
'iib_index_db_artifact_template': '{registry}/index-db:{tag}',
441+
'iib_index_db_oras_auth_path': '',
441442
}
442-
mock_get_image_digest.return_value = 'sha256:abc'
443+
mock_run_cmd.return_value = '{"digest": "sha256:abc"}'
443444
mock_get_is_digest.return_value = 'sha256:abc'
444445
tag = 'test-tag'
445446

446447
result = verify_indexdb_cache_sync(tag)
447448

448449
assert result is True
449-
mock_get_image_digest.assert_called_once_with('test-artifact-registry/index-db:test-tag')
450+
mock_run_cmd.assert_called_once_with(
451+
['oras', 'manifest', 'fetch', '--descriptor', 'test-artifact-registry/index-db:test-tag'],
452+
exc_msg='Failed to fetch manifest descriptor for test-artifact-registry/index-db:test-tag',
453+
)
450454
mock_get_is_digest.assert_called_once_with(tag)
451455

452456

453457
@mock.patch('iib.workers.tasks.oras_utils.get_worker_config')
454458
@mock.patch('iib.workers.tasks.oras_utils.get_image_stream_digest')
455-
@mock.patch('iib.workers.tasks.oras_utils.get_image_digest')
456-
def test_verify_indexdb_cache_sync_no_match(mock_get_image_digest, mock_get_is_digest, mock_gwc):
459+
@mock.patch('iib.workers.tasks.oras_utils.run_cmd')
460+
def test_verify_indexdb_cache_sync_no_match(mock_run_cmd, mock_get_is_digest, mock_gwc):
457461
"""Test successful verification when digests don't match."""
458462
mock_gwc.return_value = {
459463
'iib_index_db_artifact_registry': 'test-artifact-registry',
460464
'iib_index_db_artifact_template': '{registry}/index-db:{tag}',
465+
'iib_index_db_oras_auth_path': '',
461466
}
462-
mock_get_image_digest.return_value = 'sha256:abc'
467+
mock_run_cmd.return_value = '{"digest": "sha256:abc"}'
463468
mock_get_is_digest.return_value = 'sha256:xyz'
464469
tag = 'test-tag'
465470

466471
result = verify_indexdb_cache_sync(tag)
467472

468473
assert result is False
469-
mock_get_image_digest.assert_called_once_with('test-artifact-registry/index-db:test-tag')
474+
mock_run_cmd.assert_called_once_with(
475+
['oras', 'manifest', 'fetch', '--descriptor', 'test-artifact-registry/index-db:test-tag'],
476+
exc_msg='Failed to fetch manifest descriptor for test-artifact-registry/index-db:test-tag',
477+
)
470478
mock_get_is_digest.assert_called_once_with(tag)
471479

472480

481+
@mock.patch('os.path.exists')
482+
@mock.patch('iib.workers.tasks.oras_utils.get_worker_config')
483+
@mock.patch('iib.workers.tasks.oras_utils.get_image_stream_digest')
484+
@mock.patch('iib.workers.tasks.oras_utils.run_cmd')
485+
def test_verify_indexdb_cache_sync_with_oras_auth(
486+
mock_run_cmd, mock_get_is_digest, mock_gwc, mock_exists
487+
):
488+
"""Test that --registry-config is passed when oras auth path exists."""
489+
mock_gwc.return_value = {
490+
'iib_index_db_artifact_registry': 'test-artifact-registry',
491+
'iib_index_db_artifact_template': '{registry}/index-db:{tag}',
492+
'iib_index_db_oras_auth_path': '/path/to/oras/config.json',
493+
}
494+
mock_exists.return_value = True
495+
mock_run_cmd.return_value = '{"digest": "sha256:abc"}'
496+
mock_get_is_digest.return_value = 'sha256:abc'
497+
tag = 'test-tag'
498+
499+
result = verify_indexdb_cache_sync(tag)
500+
501+
assert result is True
502+
mock_run_cmd.assert_called_once_with(
503+
[
504+
'oras',
505+
'manifest',
506+
'fetch',
507+
'--descriptor',
508+
'--registry-config',
509+
'/path/to/oras/config.json',
510+
'test-artifact-registry/index-db:test-tag',
511+
],
512+
exc_msg='Failed to fetch manifest descriptor for test-artifact-registry/index-db:test-tag',
513+
)
514+
515+
473516
@mock.patch('iib.workers.tasks.oras_utils.get_worker_config')
474517
@mock.patch('iib.workers.tasks.oras_utils.set_registry_auths')
475518
@mock.patch('iib.workers.tasks.oras_utils.run_cmd')

0 commit comments

Comments
 (0)