From e1b7a103f141b3fafc9b234aeefdaf44bc550785 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 27 Jan 2021 08:12:00 -0600 Subject: [PATCH] cephadm: return repo_digests (plural) in pull/inspect output When we inspect a (pulled) image, return all of the repo digests. Update the mgr/cephadm code accordingly to match. Signed-off-by: Sage Weil (cherry picked from commit e9333972c1b84ebdfe43c8f686d74d4c859eedf1) --- src/cephadm/cephadm | 8 +++----- src/cephadm/tests/test_cephadm.py | 9 +++++---- src/pybind/mgr/cephadm/module.py | 5 +++-- src/pybind/mgr/cephadm/serve.py | 12 +++++++----- src/pybind/mgr/cephadm/tests/test_cephadm.py | 2 +- src/pybind/mgr/cephadm/tests/test_upgrade.py | 2 +- src/pybind/mgr/cephadm/upgrade.py | 19 ++++++++++--------- src/pybind/mgr/cephadm/utils.py | 2 +- 8 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/cephadm/cephadm b/src/cephadm/cephadm index c636ca85c5b52..6f492e7af7c5a 100755 --- a/src/cephadm/cephadm +++ b/src/cephadm/cephadm @@ -3171,17 +3171,15 @@ def command_inspect_image(ctx): 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 diff --git a/src/cephadm/tests/test_cephadm.py b/src/cephadm/tests/test_cephadm.py index e608097efe451..c98c9374a151f 100644 --- a/src/cephadm/tests/test_cephadm.py +++ b/src/cephadm/tests/test_cephadm.py @@ -258,19 +258,20 @@ default via fe80::2480:28ec:5097:3fe2 dev wlp2s0 proto ra metric 20600 pref medi 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): diff --git a/src/pybind/mgr/cephadm/module.py b/src/pybind/mgr/cephadm/module.py index a6ffdb4a037be..ef4df310007e4 100644 --- a/src/pybind/mgr/cephadm/module.py +++ b/src/pybind/mgr/cephadm/module.py @@ -2210,8 +2210,9 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule, '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) diff --git a/src/pybind/mgr/cephadm/serve.py b/src/pybind/mgr/cephadm/serve.py index 9c91c743011c8..bf4c7cccfe10d 100644 --- a/src/pybind/mgr/cephadm/serve.py +++ b/src/pybind/mgr/cephadm/serve.py @@ -686,15 +686,17 @@ class CephadmServe: 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 @@ -995,7 +997,7 @@ class CephadmServe: 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 diff --git a/src/pybind/mgr/cephadm/tests/test_cephadm.py b/src/pybind/mgr/cephadm/tests/test_cephadm.py index 840e82d0167e5..21b1b55d6ad87 100644 --- a/src/pybind/mgr/cephadm/tests/test_cephadm.py +++ b/src/pybind/mgr/cephadm/tests/test_cephadm.py @@ -939,7 +939,7 @@ class TestCephadm(object): @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", [ diff --git a/src/pybind/mgr/cephadm/tests/test_upgrade.py b/src/pybind/mgr/cephadm/tests/test_upgrade.py index 3815253409811..9599a73efc108 100644 --- a/src/pybind/mgr/cephadm/tests/test_upgrade.py +++ b/src/pybind/mgr/cephadm/tests/test_upgrade.py @@ -65,7 +65,7 @@ def test_upgrade_run(use_repo_digest, cephadm_module: CephadmOrchestrator): 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)', }))): diff --git a/src/pybind/mgr/cephadm/upgrade.py b/src/pybind/mgr/cephadm/upgrade.py index 0ab405ff637c8..b83afe94693ce 100644 --- a/src/pybind/mgr/cephadm/upgrade.py +++ b/src/pybind/mgr/cephadm/upgrade.py @@ -2,7 +2,7 @@ import json 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 @@ -21,7 +21,7 @@ class UpgradeState: 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, @@ -29,7 +29,7 @@ class UpgradeState: 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 @@ -39,7 +39,7 @@ class UpgradeState: '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, @@ -75,10 +75,11 @@ class CephadmUpgrade: 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() @@ -282,11 +283,11 @@ class CephadmUpgrade: 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', { @@ -307,7 +308,7 @@ class CephadmUpgrade: 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 '): diff --git a/src/pybind/mgr/cephadm/utils.py b/src/pybind/mgr/cephadm/utils.py index 48c3d837c4265..12574437b13c7 100644 --- a/src/pybind/mgr/cephadm/utils.py +++ b/src/pybind/mgr/cephadm/utils.py @@ -31,7 +31,7 @@ cephadmNoImage = CephadmNoImage.token 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: -- 2.39.5