From 3295691e6b0178e3d30feb53ceaad7db398fa451 Mon Sep 17 00:00:00 2001 From: Ondrej Kubik Date: Sat, 6 Jan 2024 02:07:29 +0000 Subject: [PATCH 1/5] console_conf: use 'console-conf' as project name 'project' value is used to construct /run/ path Other parts are already using 'console-conf', prefer this syntax. In the future we might consider using SNAP_NAME, and this '_' are not permitted as part of the snap name. Signed-off-by: Ondrej Kubik --- console_conf/core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/console_conf/core.py b/console_conf/core.py index 78e1af7c..36e4aee4 100644 --- a/console_conf/core.py +++ b/console_conf/core.py @@ -26,7 +26,7 @@ log = logging.getLogger("console_conf.core") class ConsoleConf(TuiApplication): from console_conf import controllers as controllers_mod - project = "console_conf" + project = "console-conf" make_model = ConsoleConfModel @@ -44,7 +44,7 @@ class ConsoleConf(TuiApplication): class RecoveryChooser(TuiApplication): from console_conf import controllers as controllers_mod - project = "console_conf" + project = "console-conf" controllers = [ "RecoveryChooserWelcome", From f3043cde88d04bc4c33d2c0f50e27b5e69262910 Mon Sep 17 00:00:00 2001 From: Maciej Borzecki Date: Tue, 6 Feb 2024 11:42:54 +0100 Subject: [PATCH 2/5] console_conf/core: use a common project for console-conf related apps Make sure that console-conf related apps use the same value for project, which results in using the same shared state directory. Signed-off-by: Maciej Borzecki --- console_conf/core.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/console_conf/core.py b/console_conf/core.py index 36e4aee4..c9b4585b 100644 --- a/console_conf/core.py +++ b/console_conf/core.py @@ -14,6 +14,7 @@ # along with this program. If not, see . import logging +import os from console_conf.models.console_conf import ConsoleConfModel from console_conf.models.systems import RecoverySystemsModel @@ -22,11 +23,17 @@ from subiquitycore.tui import TuiApplication log = logging.getLogger("console_conf.core") +# project is used to build the state directory path under /run/, which usually +# ends up as /run/console-conf. Note this should only be changed in +# coordination with console-conf-wrapper and any other glue shipped with Ubuntu +# Core boot base +CONSOLE_CONF_PROJECT = os.getenv("SNAP_INSTANCE_NAME", "console-conf") + class ConsoleConf(TuiApplication): from console_conf import controllers as controllers_mod - project = "console-conf" + project = CONSOLE_CONF_PROJECT make_model = ConsoleConfModel @@ -44,7 +51,7 @@ class ConsoleConf(TuiApplication): class RecoveryChooser(TuiApplication): from console_conf import controllers as controllers_mod - project = "console-conf" + project = CONSOLE_CONF_PROJECT controllers = [ "RecoveryChooserWelcome", From 592887b540385cb71e856363794b80a6919c4710 Mon Sep 17 00:00:00 2001 From: Maciej Borzecki Date: Tue, 6 Feb 2024 11:43:48 +0100 Subject: [PATCH 3/5] console_conf/controllers/identity: store login details in project state directory Since we set a project name centrally, it implies a specific path to the state directory. Instead of hardcoding the same value directly again in the controller code, use the application level state directory. Signed-off-by: Maciej Borzecki --- console_conf/controllers/identity.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/console_conf/controllers/identity.py b/console_conf/controllers/identity.py index e2b44331..967818ee 100644 --- a/console_conf/controllers/identity.py +++ b/console_conf/controllers/identity.py @@ -183,8 +183,7 @@ class IdentityController(TuiController): "realname": email, "username": data["username"], } - os.makedirs("/run/console-conf", exist_ok=True) - login_details_path = "/run/console-conf/login-details.txt" + login_details_path = self.app.state_path("login-details.txt") self.model.add_user(result) ips = [] net_model = self.app.base_model.network From 0764bb50b9344be123c000279378021445257fb6 Mon Sep 17 00:00:00 2001 From: Maciej Borzecki Date: Tue, 6 Feb 2024 11:45:29 +0100 Subject: [PATCH 4/5] console_conf/controllers: add unit test for identity controller Signed-off-by: Maciej Borzecki --- .../controllers/tests/test_identity.py | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 console_conf/controllers/tests/test_identity.py diff --git a/console_conf/controllers/tests/test_identity.py b/console_conf/controllers/tests/test_identity.py new file mode 100644 index 00000000..1522e162 --- /dev/null +++ b/console_conf/controllers/tests/test_identity.py @@ -0,0 +1,58 @@ +# Copyright 2024 Canonical, Ltd. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +import os.path +import tempfile +import unittest +from unittest.mock import MagicMock, patch + +from console_conf.controllers.identity import IdentityController +from subiquitycore.models.network import NetworkDev +from subiquitycore.tests.mocks import make_app + + +class TestIdentityController(unittest.TestCase): + @patch("os.ttyname", return_value="/dev/tty1") + @patch("console_conf.controllers.identity.get_core_version", return_value="24") + @patch("console_conf.controllers.identity.run_command") + def test_snap_integration(self, run_command, core_version, ttyname): + with tempfile.TemporaryDirectory(suffix="console-conf-test") as statedir: + proc_mock = MagicMock() + run_command.return_value = proc_mock + proc_mock.returncode = 0 + proc_mock.stdout = '{"username":"foo"}' + + app = make_app() + app.opts.dry_run = False + network_model = MagicMock() + mock_devs = [MagicMock(spec=NetworkDev)] + network_model.get_all_netdevs.return_value = mock_devs + mock_devs[0].actual_global_ip_addresses = ["1.2.3.4"] + app.base_model.network = network_model + app.urwid_loop = MagicMock() + + def state_path(*parts): + return os.path.join(statedir, *parts) + + app.state_path = MagicMock(side_effect=state_path) + + c = IdentityController(app) + c.identity_done("foo@bar.com") + run_command.assert_called_with( + ["snap", "create-user", "--sudoer", "--json", "foo@bar.com"] + ) + + with open(os.path.join(statedir, "login-details.txt")) as inf: + data = inf.read() + self.assertIn("Ubuntu Core 24 on 1.2.3.4 (tty1)\n", data) From 87efd8aa18bc1d94d6018c42d61e61a480d40d98 Mon Sep 17 00:00:00 2001 From: Maciej Borzecki Date: Tue, 6 Feb 2024 14:56:27 +0100 Subject: [PATCH 5/5] console_conf: use snap helper for obtaining project name Signed-off-by: Maciej Borzecki --- console_conf/core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/console_conf/core.py b/console_conf/core.py index c9b4585b..257c5e1f 100644 --- a/console_conf/core.py +++ b/console_conf/core.py @@ -14,11 +14,11 @@ # along with this program. If not, see . import logging -import os from console_conf.models.console_conf import ConsoleConfModel from console_conf.models.systems import RecoverySystemsModel from subiquitycore.prober import Prober +from subiquitycore.snap import snap_name from subiquitycore.tui import TuiApplication log = logging.getLogger("console_conf.core") @@ -27,7 +27,7 @@ log = logging.getLogger("console_conf.core") # ends up as /run/console-conf. Note this should only be changed in # coordination with console-conf-wrapper and any other glue shipped with Ubuntu # Core boot base -CONSOLE_CONF_PROJECT = os.getenv("SNAP_INSTANCE_NAME", "console-conf") +CONSOLE_CONF_PROJECT = snap_name() or "console-conf" class ConsoleConf(TuiApplication):