]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/cephadm: store contianer registry credentials in config-key
authorDaniel Pivonka <dpivonka@redhat.com>
Wed, 10 Nov 2021 16:18:06 +0000 (11:18 -0500)
committerDaniel Pivonka <dpivonka@redhat.com>
Wed, 1 Dec 2021 17:30:00 +0000 (12:30 -0500)
Signed-off-by: Daniel Pivonka <dpivonka@redhat.com>
doc/cephadm/install.rst
qa/suites/orch/cephadm/mgr-nfs-upgrade/4-final.yaml
src/cephadm/cephadm
src/pybind/mgr/cephadm/migrations.py
src/pybind/mgr/cephadm/module.py
src/pybind/mgr/cephadm/serve.py
src/pybind/mgr/cephadm/tests/test_cephadm.py

index 08996c8fc2365e9b84c073f60cbb8a62c58e9edf..95d65380afa11b6c44a2aec0f563d41842b8e713 100644 (file)
@@ -213,17 +213,13 @@ available options.
   designate with this option must have passwordless sudo access.
 
 * If you are using a container on an authenticated registry that requires
-  login, you may add the three arguments:
-  #. ``--registry-url <url of registry>``
-
-  #. ``--registry-username <username of account on registry>``
+  login, you may add the argument:
 
-  #. ``--registry-password <password of account on registry>`` 
+  * ``--registry-json <path to json file>`` 
 
-  OR
+  example contents of JSON file with login info::
 
-  * ``--registry-json <json file with login info>`` 
+      {"url":"REGISTRY_URL", "username":"REGISTRY_USERNAME", "password":"REGISTRY_PASSWORD"}
   
   Cephadm will attempt to log in to this registry so it can pull your container
   and then store the login info in its config database. Other hosts added to
index b1957d9d62880f3febb0fc9eba88a800ac994f5b..2a834ead4c06909bc60ece482b02a6d999679c32 100644 (file)
@@ -7,4 +7,4 @@ tasks:
       - ceph nfs cluster ls | grep foo
       - ceph nfs export ls foo --detailed
       - rados -p .nfs --all ls -
-      - ceph config get mgr mgr/cephadm/migration_current | grep 4
+      - ceph config get mgr mgr/cephadm/migration_current | grep 5
index 1a6b7dcd333f965ab4952d12ec37d33f63815e6b..a9b10ffa33ac4aa6d158779efa5a4fc424d23b52 100755 (executable)
@@ -4862,9 +4862,8 @@ def command_bootstrap(ctx):
         prepare_ssh(ctx, cli, wait_for_mgr_restart)
 
     if ctx.registry_url and ctx.registry_username and ctx.registry_password:
-        cli(['config', 'set', 'mgr', 'mgr/cephadm/registry_url', ctx.registry_url, '--force'])
-        cli(['config', 'set', 'mgr', 'mgr/cephadm/registry_username', ctx.registry_username, '--force'])
-        cli(['config', 'set', 'mgr', 'mgr/cephadm/registry_password', ctx.registry_password, '--force'])
+        registry_credentials = {'url': ctx.registry_url, 'username': ctx.registry_username, 'password': ctx.registry_password}
+        cli(['config-key', 'set', 'mgr/cephadm/registry_credentials', json.dumps(registry_credentials)])
 
     cli(['config', 'set', 'mgr', 'mgr/cephadm/container_init', str(ctx.container_init), '--force'])
 
index b66eedb6907ac7abc7a6dfa3bc6c9620a56b95de..95ec5d28770eca20f4e303051ba2c753330a184e 100644 (file)
@@ -12,7 +12,7 @@ from orchestrator import OrchestratorError, DaemonDescription
 if TYPE_CHECKING:
     from .module import CephadmOrchestrator
 
-LAST_MIGRATION = 4
+LAST_MIGRATION = 5
 
 logger = logging.getLogger(__name__)
 
@@ -72,6 +72,10 @@ class Migrations:
             if self.migrate_3_4():
                 self.set(4)
 
+        if self.mgr.migration_current == 4:
+            if self.migrate_4_5():
+                self.set(5)
+
     def migrate_0_1(self) -> bool:
         """
         Migration 0 -> 1
@@ -273,6 +277,38 @@ class Migrations:
             )
         return True
 
+    def migrate_4_5(self) -> bool:
+        registry_url = self.mgr.get_module_option('registry_url')
+        registry_username = self.mgr.get_module_option('registry_username')
+        registry_password = self.mgr.get_module_option('registry_password')
+        if registry_url and registry_username and registry_password:
+
+            registry_credentials = {'url': registry_url,
+                                    'username': registry_username, 'password': registry_password}
+            self.mgr.set_store('registry_credentials', json.dumps(registry_credentials))
+
+            self.mgr.set_module_option('registry_url', None)
+            self.mgr.check_mon_command({
+                'prefix': 'config rm',
+                'who': 'mgr',
+                'key': 'mgr/cephadm/registry_url',
+            })
+            self.mgr.set_module_option('registry_username', None)
+            self.mgr.check_mon_command({
+                'prefix': 'config rm',
+                'who': 'mgr',
+                'key': 'mgr/cephadm/registry_username',
+            })
+            self.mgr.set_module_option('registry_password', None)
+            self.mgr.check_mon_command({
+                'prefix': 'config rm',
+                'who': 'mgr',
+                'key': 'mgr/cephadm/registry_password',
+            })
+
+            self.mgr.log.info('Done migrating registry login info')
+        return True
+
 
 def queue_migrate_nfs_spec(mgr: "CephadmOrchestrator", spec_dict: Dict[Any, Any]) -> None:
     """
index c968d956e09d76bb9d3fa9d6062d06faa2c8a567..859d0799ab1870410957e6ea033aeac164cbc0aa 100644 (file)
@@ -277,6 +277,7 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule,
             default='*',
             desc='PlacementSpec describing on which hosts to manage /etc/ceph/ceph.conf',
         ),
+        # not used anymore
         Option(
             'registry_url',
             type='str',
@@ -295,6 +296,7 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule,
             default=None,
             desc='Custom repository password'
         ),
+        ####
         Option(
             'registry_insecure',
             type='bool',
@@ -953,14 +955,12 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule,
         if not (url and username and password) and (inbuf is None or len(inbuf) == 0):
             return -errno.EINVAL, "", ("Invalid arguments. Please provide arguments <url> <username> <password> "
                                        "or -i <login credentials json file>")
-        elif not (url and username and password):
+        elif (url and username and password):
+            registry_json = {'url': url, 'username': username, 'password': password}
+        else:
             assert isinstance(inbuf, str)
-            login_info = json.loads(inbuf)
-            if "url" in login_info and "username" in login_info and "password" in login_info:
-                url = login_info["url"]
-                username = login_info["username"]
-                password = login_info["password"]
-            else:
+            registry_json = json.loads(inbuf)
+            if "url" not in registry_json or "username" not in registry_json or "password" not in registry_json:
                 return -errno.EINVAL, "", ("json provided for custom registry login did not include all necessary fields. "
                                            "Please setup json file as\n"
                                            "{\n"
@@ -968,6 +968,7 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule,
                                            " \"username\": \"REGISTRY_USERNAME\",\n"
                                            " \"password\": \"REGISTRY_PASSWORD\"\n"
                                            "}\n")
+
         # verify login info works by attempting login on random host
         host = None
         for host_name in self.inventory.keys():
@@ -975,14 +976,12 @@ class CephadmOrchestrator(orchestrator.Orchestrator, MgrModule,
             break
         if not host:
             raise OrchestratorError('no hosts defined')
-        r = self.wait_async(CephadmServe(self)._registry_login(host, url, username, password))
+        r = self.wait_async(CephadmServe(self)._registry_login(host, registry_json))
         if r is not None:
             return 1, '', r
         # if logins succeeded, store info
         self.log.debug("Host logins successful. Storing login info.")
-        self.set_module_option('registry_url', url)
-        self.set_module_option('registry_username', username)
-        self.set_module_option('registry_password', password)
+        self.set_store('registry_credentials', json.dumps(registry_json))
         # distribute new login info to all hosts
         self.cache.distribute_new_registry_login_info()
         return 0, "registry login scheduled", ''
index 9e3f9c0927f84a7ed1ca0a0cb1f665f67af4185c..4802b1d7c4a736dc0d655ea083033a4fb1a18272 100644 (file)
@@ -242,10 +242,10 @@ class CephadmServe:
                         failures.append(r)
                 self.mgr.cache.metadata_up_to_date[host] = True
 
-            if self.mgr.cache.host_needs_registry_login(host) and self.mgr.registry_url:
+            if self.mgr.cache.host_needs_registry_login(host) and self.mgr.get_store('registry_credentials'):
                 self.log.debug(f"Logging `{host}` into custom registry")
-                r = self.mgr.wait_async(self._registry_login(host, self.mgr.registry_url,
-                                                             self.mgr.registry_username, self.mgr.registry_password))
+                r = self.mgr.wait_async(self._registry_login(
+                    host, json.loads(str(self.mgr.get_store('registry_credentials')))))
                 if r:
                     bad_hosts.append(r)
 
@@ -1096,8 +1096,7 @@ class CephadmServe:
                     daemon_spec.extra_args.append('--allow-ptrace')
 
                 if self.mgr.cache.host_needs_registry_login(daemon_spec.host) and self.mgr.registry_url:
-                    await self._registry_login(daemon_spec.host, self.mgr.registry_url,
-                                               self.mgr.registry_username, self.mgr.registry_password)
+                    await self._registry_login(daemon_spec.host, json.loads(str(self.mgr.get_store('registry_credentials'))))
 
                 self.log.info('%s daemon %s on %s' % (
                     'Reconfiguring' if reconfig else 'Deploying',
@@ -1326,8 +1325,7 @@ class CephadmServe:
         if not host:
             raise OrchestratorError('no hosts defined')
         if self.mgr.cache.host_needs_registry_login(host) and self.mgr.registry_url:
-            await self._registry_login(host, self.mgr.registry_url,
-                                       self.mgr.registry_username, self.mgr.registry_password)
+            await self._registry_login(host, json.loads(str(self.mgr.get_store('registry_credentials'))))
 
         pullargs: List[str] = []
         if self.mgr.registry_insecure:
@@ -1344,19 +1342,15 @@ class CephadmServe:
         return r
 
     # function responsible for logging single host into custom registry
-    async def _registry_login(self, host: str, url: Optional[str], username: Optional[str], password: Optional[str]) -> Optional[str]:
-        self.log.debug(f"Attempting to log host {host} into custom registry @ {url}")
+    async def _registry_login(self, host: str, registry_json: Dict[str, str]) -> Optional[str]:
+        self.log.debug(
+            f"Attempting to log host {host} into custom registry @ {registry_json['url']}")
         # want to pass info over stdin rather than through normal list of args
-        args_str = json.dumps({
-            'url': url,
-            'username': username,
-            'password': password,
-        })
         out, err, code = await self._run_cephadm(
             host, 'mon', 'registry-login',
-            ['--registry-json', '-'], stdin=args_str, error_ok=True)
+            ['--registry-json', '-'], stdin=json.dumps(registry_json), error_ok=True)
         if code:
-            return f"Host {host} failed to login to {url} as {username} with given password"
+            return f"Host {host} failed to login to {registry_json['url']} as {registry_json['username']} with given password"
         return None
 
     async def _deploy_cephadm_binary(self, host: str, addr: Optional[str] = None) -> None:
index 889192a332be6a29a507dd06abf518ca586d6e22..b564039ce2d2c4e0f34d95496371f7ca428165b8 100644 (file)
@@ -1480,9 +1480,8 @@ class TestCephadm(object):
     @mock.patch("cephadm.serve.CephadmServe._run_cephadm")
     def test_registry_login(self, _run_cephadm, cephadm_module: CephadmOrchestrator):
         def check_registry_credentials(url, username, password):
-            assert cephadm_module.get_module_option('registry_url') == url
-            assert cephadm_module.get_module_option('registry_username') == username
-            assert cephadm_module.get_module_option('registry_password') == password
+            assert json.loads(cephadm_module.get_store('registry_credentials')) == {
+                'url': url, 'username': username, 'password': password}
 
         _run_cephadm.side_effect = async_side_effect(('{}', '', 0))
         with with_host(cephadm_module, 'test'):