From 0ed9f1f1cad733817a53754f8fd16146fc41643e Mon Sep 17 00:00:00 2001 From: Dermot Bradley Date: Sat, 22 Jul 2023 04:36:05 +0100 Subject: [PATCH] cc_keyboard: add Alpine support --- cloudinit/config/cc_keyboard.py | 14 ++++++- cloudinit/distros/alpine.py | 20 +++++++++- tests/unittests/config/test_cc_keyboard.py | 44 ++++++++++++++++++++++ 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/cloudinit/config/cc_keyboard.py b/cloudinit/config/cc_keyboard.py index 5e61a0da67da..c87abbd6fff0 100644 --- a/cloudinit/config/cc_keyboard.py +++ b/cloudinit/config/cc_keyboard.py @@ -16,12 +16,13 @@ from cloudinit.settings import PER_INSTANCE # FIXME: setting keyboard layout should be supported by all OSes. -# But currently only implemented for Linux distributions that use systemd. +# But currently only implemented for Linux distributions that use systemd, +# plus Alpine Linux. DEFAULT_KEYBOARD_MODEL = "pc105" supported_distros = distros.Distro.expand_osfamily( - ["arch", "debian", "redhat", "suse"] + ["alpine", "arch", "debian", "redhat", "suse"] ) meta: MetaSchema = { @@ -48,6 +49,15 @@ options: compose:rwin """ ), + dedent( + """\ + # For Alpine Linux set specific keyboard layout and variant. + # Model and options are ignored. + keyboard: + layout: gb + variant: gb-extd + """ + ), ], "frequency": PER_INSTANCE, "activate_by_schema_keys": ["keyboard"], diff --git a/cloudinit/distros/alpine.py b/cloudinit/distros/alpine.py index 8a93665a2ffb..9fadbe15686f 100644 --- a/cloudinit/distros/alpine.py +++ b/cloudinit/distros/alpine.py @@ -6,10 +6,14 @@ # # This file is part of cloud-init. See LICENSE file for license information. -from cloudinit import distros, helpers, subp, util +from cloudinit import distros, helpers +from cloudinit import log as logging +from cloudinit import subp, util from cloudinit.distros.parsers.hostname import HostnameConf from cloudinit.settings import PER_INSTANCE +LOG = logging.getLogger(__name__) + NETWORK_FILE_HEADER = """\ # This file is generated from information provided by the datasource. Changes # to it will not persist across an instance reboot. To disable cloud-init's @@ -103,6 +107,20 @@ def _read_hostname(self, filename, default=None): def _get_localhost_ip(self): return "127.0.1.1" + def set_keymap(self, layout, model, variant, options): + if not layout: + LOG.error("Keyboard layout not specified.") + return + if not variant: + LOG.error("Keyboard variant not specified.") + return + if model: + LOG.info("Keyboard model is ignored for Alpine Linux.") + if options: + LOG.info("Keyboard options are ignored for Alpine Linux.") + + subp.subp(["setup-keymap", layout, variant]) + def set_timezone(self, tz): distros.set_etc_timezone(tz=tz, tz_file=self._find_tz_file(tz)) diff --git a/tests/unittests/config/test_cc_keyboard.py b/tests/unittests/config/test_cc_keyboard.py index 00fad9ff8fbc..dd794f0febf0 100644 --- a/tests/unittests/config/test_cc_keyboard.py +++ b/tests/unittests/config/test_cc_keyboard.py @@ -6,12 +6,15 @@ import pytest +from cloudinit.config import cc_keyboard from cloudinit.config.schema import ( SchemaValidationError, get_schema, validate_cloudconfig_schema, ) from tests.unittests.helpers import skipUnlessJsonSchema +from tests.unittests.util import get_cloud +from unittest import mock class TestKeyboard: @@ -73,5 +76,46 @@ def test_schema_validation(self, config, error_msg): with pytest.raises(SchemaValidationError, match=error_msg): validate_cloudconfig_schema(config, schema, strict=True) + @mock.patch("cloudinit.distros.Distro.uses_systemd") + @mock.patch("cloudinit.distros.subp.subp") + def test_systemd_linux_cmd(self, m_subp, m_uses_systemd, *args): + """Ubuntu runs localectl""" + cfg = {"keyboard": {"layout": "us", "variant": "us"}} + layout = "us" + model = "pc105" + variant = "us" + options = "" + m_uses_systemd.return_value = True + cloud = get_cloud("ubuntu") + cc_keyboard.handle("cc_keyboard", cfg, cloud, []) + locale_calls = [ + mock.call( + [ + "localectl", + "set-x11-keymap", + layout, + model, + variant, + options, + ] + ), + mock.call( + ["systemctl", "restart", "console-setup"], + capture=True, + rcs=None, + ), + ] + m_subp.assert_has_calls(locale_calls) + + @mock.patch("cloudinit.distros.subp.subp") + def test_alpine_linux_cmd(self, m_subp, *args): + """Alpine Linux runs setup-keymap""" + cfg = {"keyboard": {"layout": "us", "variant": "us"}} + layout = "us" + variant = "us" + cloud = get_cloud("alpine") + cc_keyboard.handle("cc_keyboard", cfg, cloud, []) + m_subp.assert_called_once_with(["setup-keymap", layout, variant]) + # vi: ts=4 expandtab