diff --git a/confconsole.py b/confconsole.py index 3faca78..7f76f0e 100755 --- a/confconsole.py +++ b/confconsole.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 # Copyright (c) 2008 Alon Swartz - all rights reserved -"""TurnKey Configuration Console +"""Keel Linux Configuration Console Options: -h, --help Display this help and exit @@ -40,6 +40,11 @@ PLUGIN_PATH = os.path.join( os.path.dirname(os.path.realpath(__file__)), "plugins.d" ) +# The name at the top of every screen and, unless APPNAME_PATH names the +# appliance otherwise, before the hostname in the menu titles. +BRAND = "Keel Linux" +TITLE = f"{BRAND} Configuration Console" +APPNAME_PATH = "/etc/appname" handler = JournalHandler(SYSLOG_IDENTIFIER="confconsole") handler.setFormatter(logging.Formatter("%(name)s: %(message)s")) @@ -399,20 +404,19 @@ def __init__( eventManager: plugin.EventManager, advanced_enabled: bool = True, ) -> None: - title = "TurnKey GNU/Linux Configuration Console" self.width = 65 self.height = 25 - self.console = Console(title, self.width, self.height) + self.console = Console(TITLE, self.width, self.height) # sometimes it would be nice to have the appname be something other # than the hostname. Allow developers to create file containing the # appname in /etc/appname try: - with open("/etc/appname", 'r') as fob: + with open(APPNAME_PATH, 'r') as fob: self.appname = fob.read().rstrip() except FileNotFoundError: - self.appname = f"TurnKey Linux {netinfo.get_hostname().upper()}" + self.appname = f"{BRAND} {netinfo.get_hostname().upper()}" self.installer = Installer(path="/usr/bin/di-live") diff --git a/debian/changelog b/debian/changelog index de2de47..f450075 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,38 @@ +confconsole (2.2.3+keel10) trixie; urgency=low + + * Every screen names Keel Linux. The backtitle read "TurnKey GNU/Linux + Configuration Console" and, without /etc/appname, the menus were + titled "TurnKey Linux "; they read "Keel Linux + Configuration Console" and "Keel Linux " (BRAND, TITLE). + /etc/appname still names the appliance when it exists. The role and + Keel Cloud first boot screens (keelfirstboot.py) read "Keel Linux - + First boot configuration", the backtitle of the inithooks dialogs + they run between, instead of "Keel - First boot configuration". + * Mail relay: "this server" sends mail directly, not "TurnKey servers"; + the sign up link is Brevo's own page instead of TurnKey's referral + link through the TurnKey Hub, and the SendinBlue entry is Brevo's + relay, not TurnKey's preferred gateway. Its key is now Brevo, the + name the code after the menu already tested for: with the old key + the Brevo host and port were never filled in. + * Let's Encrypt and the security update settings point at this + repository's documentation (docs/Lets_encrypt.rst, + docs/System_settings.rst) instead of turnkeylinux.org, and a missing + DNS provider list is reported to the confconsole issues here, not to + TurnKey. + * --help says "Keel Linux Configuration Console" (the module + docstring). turnkey-lexicon's help sends problems to the confconsole + issues here instead of TurnKey's forum and tracker, and no longer + calls confconsole TurnKey's. + * Kept: the turnkey-lexicon and turnkey-install-security-updates + commands (installed names, run by the screens), the Python class + name TurnkeyConsole, the package dependencies on turnkey-netinfo and + turnkey-conffile, and the copyright notices. The docs/ and README + still describe TurnKey; they are not shown on an appliance. + * tests/test_brand.py checks the backtitle, the appname and that no + string of a shipped screen names TurnKey or TKLBAM. + + -- Marcos Méndez Fri, 02 Oct 2026 04:00:00 +0000 + confconsole (2.2.3+keel9) trixie; urgency=low * Usage screen: the maintainer's console art in tiers. keelbanner picks diff --git a/keelfirstboot.py b/keelfirstboot.py index 9df28fb..1027278 100644 --- a/keelfirstboot.py +++ b/keelfirstboot.py @@ -53,7 +53,7 @@ ROLE = "role" CLOUD = "cloud" USAGE = "Syntax: keelfirstboot.py role|cloud" -BACKTITLE = "Keel - First boot configuration" +BACKTITLE = "Keel Linux - First boot configuration" TTY = "/dev/tty" # confconsole's box height, and the rows the back title and the shadow # take on a terminal smaller than that diff --git a/plugins.d/Lets_Encrypt/get_certificate.py b/plugins.d/Lets_Encrypt/get_certificate.py index 179ecc4..9b4ed5d 100755 --- a/plugins.d/Lets_Encrypt/get_certificate.py +++ b/plugins.d/Lets_Encrypt/get_certificate.py @@ -19,11 +19,10 @@ enter each domain into a box, one domain per box. Empty boxes will be ignored. Wildcard domains are supported, but only when using DNS-01 challenge. Alias -will be auto generated, so should not be entered here. See: -https://www.turnkeylinux.org/docs/confconsole/letsencrypt#wildcard +will be auto generated, so should not be entered here. -To generate multiple certificates, please consult the advanced docs: -https://www.turnkeylinux.org/docs/letsencrypt#advanced +For wildcards and for multiple certificates, please consult the docs: +https://github.com/Keel-Linux/confconsole/blob/master/docs/Lets_encrypt.rst """ dehydrated_conf = "/etc/dehydrated" @@ -245,7 +244,8 @@ def run() -> None: "Error", f"Dehydrated not installed or {dehydrated_conf} not found," " dehydrated can be installed via apt from the Debian repos.\n\n" - "More info: www.turnkeylinux.org/docs/letsencrypt", + "More info: https://github.com/Keel-Linux/confconsole/blob/" + "master/docs/Lets_encrypt.rst", autosize=True, ) return @@ -304,7 +304,8 @@ def run() -> None: if not providers: console.msgbox( "Error", - "No providers found, please report to TurnKey", + "No providers found, please report it at" + " https://github.com/Keel-Linux/confconsole/issues", autosize=True, ) return @@ -360,8 +361,8 @@ def run() -> None: ret, values = console.form( "Lexicon configuration", "Review and adjust current lexicon configuration as" - "necessary.\n\n Please see https://www.turnkeylinux.org/docs/" - "confconsole/letsencrypt#dns-01", + "necessary.\n\n Please see https://github.com/Keel-Linux/" + "confconsole/blob/master/docs/Lets_encrypt.rst", fields, autosize=True, ) diff --git a/plugins.d/Mail_Relaying/mail_relay.py b/plugins.d/Mail_Relaying/mail_relay.py index 6543935..0521bbc 100755 --- a/plugins.d/Mail_Relaying/mail_relay.py +++ b/plugins.d/Mail_Relaying/mail_relay.py @@ -10,11 +10,11 @@ TITLE = "Mail Relay" TEXT = ( - "By default, TurnKey servers send e-mail directly. An SMTP relay provides" + "By default, this server sends e-mail directly. An SMTP relay provides" " more robust mail deliverability.\n\n" - "Send up to 9000 emails per month with a free Brevo account. To sign up," - " open the below URL in your web browser and follow the prompts:\n\n" - "https://hub.turnkeylinux.org/email" + "Brevo (formerly SendinBlue) offers a free plan. To sign up, open the" + " below URL in your web browser and follow the prompts:\n\n" + "https://www.brevo.com/" ) FORMNOTE = ( @@ -81,7 +81,7 @@ def run(): TITLE, TEXT, [ - ("SendinBlue", "TurnKey's preferred SMTP gateway"), + ("Brevo", "Brevo (formerly SendinBlue) SMTP relay"), ("Custom", "Custom mail relay configuration"), ("Deconfigure", "Erase current mail relay settings"), ], diff --git a/plugins.d/System_Settings/Secupdates_adv_conf.py b/plugins.d/System_Settings/Secupdates_adv_conf.py index 7e13daa..229ac62 100755 --- a/plugins.d/System_Settings/Secupdates_adv_conf.py +++ b/plugins.d/System_Settings/Secupdates_adv_conf.py @@ -8,10 +8,13 @@ CONF_DEFAULT = "/etc/cron-apt/action-available.d/5-install.default" CONF_ALT = "/etc/cron-apt/action-available.d/5-install.alt" -doc_url = "www.turnkeylinux.org/secupdates#issue-res" +doc_url = ( + "https://github.com/Keel-Linux/confconsole/blob/master/docs/" + "System_settings.rst" +) info_default = """ -This is the historic and default TurnKey cronapt behaviour. Only packages \ +This is the historic and default cron-apt behaviour. Only packages \ from the repos listed in security.sources.list will be installed. \ Missing dependencies (extremely rare) will not be installed and will cause \ package removal. This package removal may cause one or more services to fail.\ diff --git a/tests/test_brand.py b/tests/test_brand.py new file mode 100644 index 0000000..aab8a35 --- /dev/null +++ b/tests/test_brand.py @@ -0,0 +1,123 @@ +"""What confconsole shows the operator names Keel Linux, not TurnKey. + +The backtitle at the top of every screen, the appliance name the menus +are titled with, and the text of the screens a Keel appliance ships are +checked for TurnKey's name and addresses. What stays, and why, is +ALLOWED: the names of commands a screen runs or tells the operator to +run, kept so that existing installs and documentation keep working. +""" + +import ast +from pathlib import Path + +import pytest + +ROOT = Path(__file__).resolve().parent.parent + +# Every Python file whose strings reach a screen. +SHOWN = [ + "confconsole.py", + "plugins.d/Mail_Relaying/mail_relay.py", + "plugins.d/Lets_Encrypt/get_certificate.py", + "plugins.d/Lets_Encrypt/dns_01.py", + "plugins.d/System_Settings/Secupdates_adv_conf.py", + "plugins.d/System_Settings/Security_Update.py", +] +# Command names, not branding: the lexicon wrapper confconsole installs +# and the security update command inithooks installs. +ALLOWED = ["turnkey-lexicon", "turnkey-install-security-updates"] + + +def strings(path: str) -> list[str]: + """Every string literal of the Python file at PATH but its docstrings + and the names it imports""" + tree = ast.parse((ROOT / path).read_text()) + skipped = set() + for node in ast.walk(tree): + if isinstance(node, (ast.Module, ast.FunctionDef, ast.ClassDef)): + if ast.get_docstring(node, clean=False) is not None: + skipped.add(id(node.body[0].value)) + return [ + node.value + for node in ast.walk(tree) + if isinstance(node, ast.Constant) + and isinstance(node.value, str) + and id(node) not in skipped + ] + + +def names_turnkey(text: str) -> bool: + for allowed in ALLOWED: + text = text.replace(allowed, "") + return "turnkey" in text.lower() or "tklbam" in text.lower() + + +class FakePluginManager: + def updateGlobals(self, values): + self.globals = values + + +@pytest.fixture +def console_title(confconsole, monkeypatch): + """The backtitle and appname a TurnkeyConsole is created with.""" + seen = {} + + class FakeConsole: + def __init__(self, title, width, height): + seen["title"] = title + + monkeypatch.setattr(confconsole, "Console", FakeConsole) + monkeypatch.setattr(confconsole.netinfo, "get_hostname", lambda: "web") + monkeypatch.setattr(confconsole, "APPNAME_PATH", "/nonexistent/appname") + tc = confconsole.TurnkeyConsole(FakePluginManager(), object()) + return seen["title"], tc.appname + + +def test_backtitle_names_keel_linux(console_title): + title, _ = console_title + assert title == "Keel Linux Configuration Console" + + +def test_appname_without_etc_appname_names_keel_linux(console_title): + _, appname = console_title + assert appname == "Keel Linux WEB" + + +def test_first_boot_screens_carry_the_inithooks_backtitle(): + # The role and Keel Cloud screens run between the inithooks dialogs, + # whose backtitle is "Keel Linux - First boot configuration" + # (Keel-Linux/inithooks libinithooks/dialog_wrapper.py); the same words + # keep the top line still as the operator moves from one to the next. + import keelfirstboot + + assert keelfirstboot.BACKTITLE == "Keel Linux - First boot configuration" + + +def test_etc_appname_still_wins(confconsole, monkeypatch, tmp_path): + path = tmp_path / "appname" + path.write_text("My Site\n") + monkeypatch.setattr(confconsole, "Console", lambda *args: None) + monkeypatch.setattr(confconsole, "APPNAME_PATH", str(path)) + tc = confconsole.TurnkeyConsole(FakePluginManager(), object()) + assert tc.appname == "My Site" + + +@pytest.mark.parametrize("path", SHOWN) +def test_no_screen_text_names_turnkey(path): + shown = [text for text in strings(path) if names_turnkey(text)] + assert shown == [] + + +def test_help_text_names_keel_linux(confconsole): + # The module docstring is what --help prints. + assert confconsole.__doc__.splitlines()[0] == ( + "Keel Linux Configuration Console" + ) + assert "turnkey" not in confconsole.USAGE.lower() + + +def test_lexicon_wrapper_sends_problems_to_keel(): + text = (ROOT / "turnkey-lexicon").read_text() + assert "turnkeylinux" not in text + assert "TurnKey" not in text + assert "https://github.com/Keel-Linux/confconsole/issues" in text diff --git a/turnkey-lexicon b/turnkey-lexicon index e6fd9f0..acfb25a 100755 --- a/turnkey-lexicon +++ b/turnkey-lexicon @@ -18,13 +18,9 @@ Then select: Advanced >> Let's Encrypt >> Get Certificate >> DNS-01 -If you encounter problems, please report to TurnKey, either via our forums: +If you encounter problems, please open an issue: - https://www.turnkeylinux.org/forum/support - -Or open an issue on our tracker: - - https://github.com/turnkeylinux/tracker/issues + https://github.com/Keel-Linux/confconsole/issues EOF exit 1 } @@ -36,7 +32,7 @@ Syntax $(basename "$0") [-h|--help] [-l|--lexicon-help] [] [