]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
cephadm: return repo_digests (plural) in pull/inspect output
authorSage Weil <sage@newdream.net>
Wed, 27 Jan 2021 14:12:00 +0000 (08:12 -0600)
committerSage Weil <sage@newdream.net>
Mon, 1 Feb 2021 23:20:14 +0000 (17:20 -0600)
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 <sage@newdream.net>
src/cephadm/cephadm
src/cephadm/tests/test_cephadm.py
src/pybind/mgr/cephadm/module.py
src/pybind/mgr/cephadm/serve.py
src/pybind/mgr/cephadm/tests/test_cephadm.py
src/pybind/mgr/cephadm/tests/test_upgrade.py
src/pybind/mgr/cephadm/upgrade.py
src/pybind/mgr/cephadm/utils.py

index d37bef123a06a8e5e2911f373b8dec81b8f750bb..d2f40eda5f2e65cf9d9531b75f4e14bf6a1ed5cd 100755 (executable)
@@ -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
 
 
index dae49a090374791f9d2f4af4b127f4d3e4c34832..1d8a5e09b2812252b24a8fb0bf32f729c4a4936e 100644 (file)
@@ -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):
index a6ffdb4a037be383e43f5b8c03f58502757cfc60..ef4df310007e4eca3ab455fc22bffc476acb6479 100644 (file)
@@ -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)
 
index 9c91c743011c8dc94b7ca7c73f31c622ad4f66de..bf4c7cccfe10d092058226fedfc080e01803f3b3 100644 (file)
@@ -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
index 840e82d0167e51bb58168204014d5a4464eb314c..21b1b55d6ad87b6baf64c1f7aec2d31edabdf695 100644 (file)
@@ -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",
                              [
index 3815253409811bfe4bfc395d572692dd52f85021..9599a73efc1081169792b44bcf35c7fd3a06989e 100644 (file)
@@ -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)',
             }))):
 
index 0ab405ff637c889822185d12abfdac912f37d772..b83afe94693ce00cbec57c38268853dd40b2bd8d 100644 (file)
@@ -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 '):
index 48c3d837c4265cb9fd679fad2fbe8dfa62c14d37..12574437b13c7d718d9d332477ce8d3b46bf1286 100644 (file)
@@ -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: