Skip to content

Commit

Permalink
server: fix when cloud-config has no default user
Browse files Browse the repository at this point in the history
If a cloud-config is sent that adjusts the users but creates no default
user, Subiquity crashes with a exception while mishandling the None.

cloudinit.distros.ug_util.extract_default is documented as returning
None in the event that the default user cannot be found.

Example bad cloud-config:
```yaml
users:
- name: ubuntu-server
```
  • Loading branch information
dbungert committed Jun 29, 2023
1 parent ef7668d commit 5bd9a4f
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 2 deletions.
5 changes: 4 additions & 1 deletion subiquity/server/server.py
Expand Up @@ -629,7 +629,10 @@ def use_passwd(passwd):

self.installer_user_name = username

if self._user_has_password(username):
if username is None:
# extract_default can return None, if there is no default user
self.installer_user_passwd_kind = PasswordKind.NONE
elif self._user_has_password(username):
# Was the password set to a random password by a version of
# cloud-init that records the username in the log? (This is the
# case we hit on upgrading the subiquity snap)
Expand Down
26 changes: 25 additions & 1 deletion subiquity/server/tests/test_server.py
Expand Up @@ -15,7 +15,7 @@

import os
import shlex
from unittest.mock import Mock
from unittest.mock import Mock, patch

from subiquitycore.utils import run_command
from subiquitycore.tests import SubiTestCase
Expand All @@ -27,6 +27,7 @@
iso_autoinstall_path,
root_autoinstall_path,
)
from subiquity.common.types import PasswordKind


class TestAutoinstallLoad(SubiTestCase):
Expand Down Expand Up @@ -150,3 +151,26 @@ async def test_interactive_sections_one(self):
mc = MetaController(make_app())
mc.app.autoinstall_config['interactive-sections'] = ['network']
self.assertEqual(['network'], await mc.interactive_sections_GET())


class TestDefaultUser(SubiTestCase):
@patch('subiquity.server.server.ug_util.normalize_users_groups',
Mock(return_value=(None, None)))
@patch('subiquity.server.server.ug_util.extract_default',
Mock(return_value=(None, None)))
@patch('subiquity.server.server.user_key_fingerprints',
Mock(side_effect=Exception('should not be called')))
async def test_no_default_user(self):
opts = Mock()
opts.dry_run = True
opts.output_base = self.tmp_dir()
opts.machine_config = 'examples/simple.json'
server = SubiquityServer(opts, None)
server.cloud = Mock()
server._user_has_password = Mock(
side_effect=Exception('should not be called'))

opts.dry_run = False # exciting!
server.set_installer_password()
self.assertIsNone(server.installer_user_name)
self.assertEqual(PasswordKind.NONE, server.installer_user_passwd_kind)

0 comments on commit 5bd9a4f

Please sign in to comment.