def get_image_info_from_inspect(out, image):
- # type: (str, str) -> Dict[str, str]
+ # type: (str, str) -> Dict[str, Union[str,List[str]]]
image_id, digests = out.split(',', 1)
if not out:
raise Error('inspect {}: empty result'.format(image))
r = {
'image_id': normalize_container_id(image_id)
- }
+ } # type: Dict[str, Union[str,List[str]]]
if digests:
- json_digests = digests[1:-1].split(' ')
- if json_digests:
- r['repo_digest'] = json_digests[0]
+ r['repo_digests'] = digests[1:-1].split(' ')
return r
def test_get_image_info_from_inspect(self):
# podman
- out = """204a01f9b0b6710dd0c0af7f37ce7139c47ff0f0105d778d7104c69282dfbbf1,["docker.io/ceph/ceph@sha256:1cc9b824e1b076cdff52a9aa3f0cc8557d879fb2fbbba0cafed970aca59a3992"]"""
+ out = """204a01f9b0b6710dd0c0af7f37ce7139c47ff0f0105d778d7104c69282dfbbf1,[docker.io/ceph/ceph@sha256:1cc9b824e1b076cdff52a9aa3f0cc8557d879fb2fbbba0cafed970aca59a3992]"""
r = cd.get_image_info_from_inspect(out, 'registry/ceph/ceph:latest')
+ print(r)
assert r == {
'image_id': '204a01f9b0b6710dd0c0af7f37ce7139c47ff0f0105d778d7104c69282dfbbf1',
- 'repo_digest': 'docker.io/ceph/ceph@sha256:1cc9b824e1b076cdff52a9aa3f0cc8557d879fb2fbbba0cafed970aca59a3992'
+ 'repo_digests': ['docker.io/ceph/ceph@sha256:1cc9b824e1b076cdff52a9aa3f0cc8557d879fb2fbbba0cafed970aca59a3992']
}
# docker
- out = """sha256:16f4549cf7a8f112bbebf7946749e961fbbd1b0838627fe619aab16bc17ce552,["quay.ceph.io/ceph-ci/ceph@sha256:4e13da36c1bd6780b312a985410ae678984c37e6a9493a74c87e4a50b9bda41f"]"""
+ out = """sha256:16f4549cf7a8f112bbebf7946749e961fbbd1b0838627fe619aab16bc17ce552,[quay.ceph.io/ceph-ci/ceph@sha256:4e13da36c1bd6780b312a985410ae678984c37e6a9493a74c87e4a50b9bda41f]"""
r = cd.get_image_info_from_inspect(out, 'registry/ceph/ceph:latest')
assert r == {
'image_id': '16f4549cf7a8f112bbebf7946749e961fbbd1b0838627fe619aab16bc17ce552',
- 'repo_digest': 'quay.ceph.io/ceph-ci/ceph@sha256:4e13da36c1bd6780b312a985410ae678984c37e6a9493a74c87e4a50b9bda41f'
+ 'repo_digests': ['quay.ceph.io/ceph-ci/ceph@sha256:4e13da36c1bd6780b312a985410ae678984c37e6a9493a74c87e4a50b9bda41f']
}
def test_dict_get(self):
'current_id': dd.container_image_id,
'current_version': dd.version,
}
- if self.use_repo_digest:
- r['target_digest'] = image_info.repo_digest
+ if self.use_repo_digest and image_info.repo_digests:
+ # FIXME: we assume the first digest is the best one to use
+ r['target_digest'] = image_info.repo_digests[0]
return json.dumps(r, indent=4, sort_keys=True)
for container_image_ref in set(settings.values()):
if not is_repo_digest(container_image_ref):
image_info = self._get_container_image_info(container_image_ref)
- if image_info.repo_digest:
- assert is_repo_digest(image_info.repo_digest), image_info
+ if image_info.repo_digests:
+ # FIXME: we assume the first digest here is the best
+ assert is_repo_digest(image_info.repo_digests[0]), image_info
digests[container_image_ref] = image_info
for entity, container_image_ref in settings.items():
if not is_repo_digest(container_image_ref):
image_info = digests[container_image_ref]
- if image_info.repo_digest:
- self.mgr.set_container_image(entity, image_info.repo_digest)
+ if image_info.repo_digests:
+ # FIXME: we assume the first digest here is the best
+ self.mgr.set_container_image(entity, image_info.repo_digests[0])
# ha-rgw needs definitve host list to create keepalived config files
# if definitive host list has changed, all ha-rgw daemons must get new
r = ContainerInspectInfo(
j['image_id'],
j.get('ceph_version'),
- j.get('repo_digest')
+ j.get('repo_digests')
)
self.log.debug(f'image {image_name} -> {r}')
return r
@mock.patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm(json.dumps({
'image_id': 'image_id',
- 'repo_digest': 'image@repo_digest',
+ 'repo_digests': ['image@repo_digest'],
})))
@pytest.mark.parametrize("use_repo_digest",
[
with mock.patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm(json.dumps({
'image_id': 'image_id',
- 'repo_digest': 'to_image@repo_digest',
+ 'repo_digests': ['to_image@repo_digest'],
'ceph_version': 'ceph version 18.2.3 (hash)',
}))):
import logging
import time
import uuid
-from typing import TYPE_CHECKING, Optional, Dict
+from typing import TYPE_CHECKING, Optional, Dict, List
import orchestrator
from cephadm.serve import CephadmServe
target_name: str,
progress_id: str,
target_id: Optional[str] = None,
- repo_digest: Optional[str] = None,
+ repo_digests: Optional[List[str]] = None,
target_version: Optional[str] = None,
error: Optional[str] = None,
paused: Optional[bool] = None,
self._target_name: str = target_name # Use CephadmUpgrade.target_image instead.
self.progress_id: str = progress_id
self.target_id: Optional[str] = target_id
- self.repo_digest: Optional[str] = repo_digest
+ self.repo_digests: Optional[List[str]] = repo_digests
self.target_version: Optional[str] = target_version
self.error: Optional[str] = error
self.paused: bool = paused or False
'target_name': self._target_name,
'progress_id': self.progress_id,
'target_id': self.target_id,
- 'repo_digest': self.repo_digest,
+ 'repo_digests': self.repo_digests,
'target_version': self.target_version,
'error': self.error,
'paused': self.paused,
assert self.upgrade_state
if not self.mgr.use_repo_digest:
return self.upgrade_state._target_name
- if not self.upgrade_state.repo_digest:
+ if not self.upgrade_state.repo_digests:
return self.upgrade_state._target_name
- return self.upgrade_state.repo_digest
+ # FIXME: we assume the first digest is the best one to use
+ return self.upgrade_state.repo_digests[0]
def upgrade_status(self) -> orchestrator.UpgradeStatusSpec:
r = orchestrator.UpgradeStatusSpec()
target_image = self.target_image
target_id = self.upgrade_state.target_id
target_version = self.upgrade_state.target_version
- if not target_id or not target_version or (self.mgr.use_repo_digest and not self.upgrade_state.repo_digest):
+ if not target_id or not target_version or (self.mgr.use_repo_digest and not self.upgrade_state.repo_digests):
# need to learn the container hash
logger.info('Upgrade: First pull of %s' % target_image)
try:
- target_id, target_version, repo_digest = CephadmServe(self.mgr)._get_container_image_info(
+ target_id, target_version, repo_digests = CephadmServe(self.mgr)._get_container_image_info(
target_image)
except OrchestratorError as e:
self._fail_upgrade('UPGRADE_FAILED_PULL', {
self.upgrade_state.target_id = target_id
# extract the version portion of 'ceph version {version} ({sha1})'
self.upgrade_state.target_version = target_version.split(' ')[2]
- self.upgrade_state.repo_digest = repo_digest
+ self.upgrade_state.repo_digests = repo_digests
self._save_upgrade_state()
target_image = self.target_image
if target_version.startswith('ceph version '):
class ContainerInspectInfo(NamedTuple):
image_id: str
ceph_version: Optional[str]
- repo_digest: Optional[str]
+ repo_digests: Optional[List[str]]
def name_to_config_section(name: str) -> ConfEntity: