From 38f84520eefaba14d4f4ae5572ea948819a3fd7d Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 6 Apr 2021 09:36:31 -0400 Subject: [PATCH] mgr/cephadm/upgrade: normalize unqualified target image If we get an unqualified target image, assume it's docker.io. This ensures that we're passing a fully-qualified target to docker|podman on the various hosts and don't end up with something different based on the per-host search path for unqualified image names. Signed-off-by: Sage Weil --- src/pybind/mgr/cephadm/module.py | 7 +++++++ src/pybind/mgr/cephadm/tests/test_upgrade.py | 16 ++++++++-------- src/pybind/mgr/cephadm/upgrade.py | 16 +++++++++++++++- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/pybind/mgr/cephadm/module.py b/src/pybind/mgr/cephadm/module.py index 2e222dc53a6..f5d4307a873 100644 --- a/src/pybind/mgr/cephadm/module.py +++ b/src/pybind/mgr/cephadm/module.py @@ -313,6 +313,12 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule, default=False, desc='Enable or disable the cephadm configuration analysis', ), + Option( + 'default_registry', + type='str', + default='docker.io', + desc='Registry to which we should normalize unqualified image names', + ), ] def __init__(self, *args: Any, **kwargs: Any): @@ -357,6 +363,7 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule, self.registry_username: Optional[str] = None self.registry_password: Optional[str] = None self.use_repo_digest = True + self.default_registry = '' self._cons: Dict[str, Tuple[remoto.backends.BaseConnection, remoto.backends.LegacyModuleExecute]] = {} diff --git a/src/pybind/mgr/cephadm/tests/test_upgrade.py b/src/pybind/mgr/cephadm/tests/test_upgrade.py index 7304ec41c36..9af6eb33991 100644 --- a/src/pybind/mgr/cephadm/tests/test_upgrade.py +++ b/src/pybind/mgr/cephadm/tests/test_upgrade.py @@ -14,16 +14,16 @@ from .fixtures import _run_cephadm, wait, with_host, with_service def test_upgrade_start(cephadm_module: CephadmOrchestrator): with with_host(cephadm_module, 'test'): assert wait(cephadm_module, cephadm_module.upgrade_start( - 'image_id', None)) == 'Initiating upgrade to image_id' + 'image_id', None)) == 'Initiating upgrade to docker.io/image_id' - assert wait(cephadm_module, cephadm_module.upgrade_status()).target_image == 'image_id' + assert wait(cephadm_module, cephadm_module.upgrade_status()).target_image == 'docker.io/image_id' - assert wait(cephadm_module, cephadm_module.upgrade_pause()) == 'Paused upgrade to image_id' + assert wait(cephadm_module, cephadm_module.upgrade_pause()) == 'Paused upgrade to docker.io/image_id' assert wait(cephadm_module, cephadm_module.upgrade_resume() - ) == 'Resumed upgrade to image_id' + ) == 'Resumed upgrade to docker.io/image_id' - assert wait(cephadm_module, cephadm_module.upgrade_stop()) == 'Stopped upgrade to image_id' + assert wait(cephadm_module, cephadm_module.upgrade_stop()) == 'Stopped upgrade to docker.io/image_id' @mock.patch("cephadm.serve.CephadmServe._run_cephadm", _run_cephadm('{}')) @@ -50,10 +50,10 @@ def test_upgrade_run(use_repo_digest, cephadm_module: CephadmOrchestrator): }): version_mock.return_value = 'ceph version 18.2.1 (somehash)' assert wait(cephadm_module, cephadm_module.upgrade_start( - 'to_image', None)) == 'Initiating upgrade to to_image' + 'to_image', None)) == 'Initiating upgrade to docker.io/to_image' assert wait(cephadm_module, cephadm_module.upgrade_status() - ).target_image == 'to_image' + ).target_image == 'docker.io/to_image' def _versions_mock(cmd): return json.dumps({ @@ -106,7 +106,7 @@ def test_upgrade_run(use_repo_digest, cephadm_module: CephadmOrchestrator): if use_repo_digest: assert image == 'to_image@repo_digest' else: - assert image == 'to_image' + assert image == 'docker.io/to_image' def test_upgrade_state_null(cephadm_module: CephadmOrchestrator): diff --git a/src/pybind/mgr/cephadm/upgrade.py b/src/pybind/mgr/cephadm/upgrade.py index 3f4c09991e8..b92d20d1a10 100644 --- a/src/pybind/mgr/cephadm/upgrade.py +++ b/src/pybind/mgr/cephadm/upgrade.py @@ -17,6 +17,20 @@ if TYPE_CHECKING: logger = logging.getLogger(__name__) +def normalize_image_digest(digest: str, default_registry: str) -> str: + # normal case: + # ceph/ceph -> docker.io/ceph/ceph + # edge cases that shouldn't ever come up: + # ubuntu -> docker.io/ubuntu (ubuntu alias for library/ubuntu) + # no change: + # quay.ceph.io/ceph/ceph -> ceph + # docker.io/ubuntu -> no change + bits = digest.split('/') + if '.' not in bits[0] or len(bits) < 3: + digest = 'docker.io/' + digest + return digest + + class UpgradeState: def __init__(self, target_name: str, @@ -171,7 +185,7 @@ class CephadmUpgrade: raise OrchestratorError(version_error) target_name = self.mgr.container_image_base + ':v' + version elif image: - target_name = image + target_name = normalize_image_digest(image, self.mgr.default_registry) else: raise OrchestratorError('must specify either image or version') if self.upgrade_state: -- 2.39.5