archinstall/tests/test_args.py

446 lines
10 KiB
Python

import json
import os
from importlib.metadata import version
from pathlib import Path
from pytest import MonkeyPatch
from archinstall.default_profiles.profile import CustomSetting, GreeterType
from archinstall.lib.args import ArchConfig, ArchConfigHandler, Arguments
from archinstall.lib.hardware import GfxDriver
from archinstall.lib.models.application import (
ApplicationConfiguration,
Audio,
AudioConfiguration,
BluetoothConfiguration,
PrintServiceConfiguration,
ZramConfiguration,
)
from archinstall.lib.models.authentication import AuthenticationConfiguration, U2FLoginConfiguration, U2FLoginMethod
from archinstall.lib.models.bootloader import Bootloader, BootloaderConfiguration
from archinstall.lib.models.device import DiskLayoutConfiguration, DiskLayoutType, Size
from archinstall.lib.models.locale import LocaleConfiguration
from archinstall.lib.models.mirrors import CustomRepository, CustomServer, MirrorConfiguration, MirrorRegion, SignCheck, SignOption
from archinstall.lib.models.network import NetworkConfiguration, Nic, NicType
from archinstall.lib.models.packages import Repository
from archinstall.lib.models.pacman import PacmanConfiguration
from archinstall.lib.models.profile import ProfileConfiguration
from archinstall.lib.models.users import Password, User
from archinstall.lib.profile.profiles_handler import profile_handler
from archinstall.lib.translationhandler import translation_handler
def test_default_args(monkeypatch: MonkeyPatch) -> None:
monkeypatch.setattr('sys.argv', ['archinstall'])
handler = ArchConfigHandler()
args = handler.args
assert args == Arguments(
config=None,
config_url=None,
creds=None,
creds_url=None,
creds_decryption_key=None,
silent=False,
dry_run=False,
script=None,
mountpoint=Path('/mnt'),
skip_ntp=False,
skip_wkd=False,
skip_boot=False,
debug=False,
offline=False,
no_pkg_lookups=False,
plugin=None,
plugin_url=None,
skip_version_check=False,
advanced=False,
)
def test_correct_parsing_args(
monkeypatch: MonkeyPatch,
config_fixture: Path,
creds_fixture: Path,
) -> None:
monkeypatch.setattr(
'sys.argv',
[
'archinstall',
'--config',
str(config_fixture),
'--config-url',
'https://example.com',
'--creds',
str(creds_fixture),
'--script',
'execution_script',
'--mountpoint',
'/tmp',
'--skip-ntp',
'--skip-wkd',
'--skip-boot',
'--debug',
'--offline',
'--no-pkg-lookups',
'--plugin',
'pytest_plugin.py',
'--skip-version-check',
'--advanced',
'--dry-run',
'--silent',
],
)
handler = ArchConfigHandler()
args = handler.args
assert args == Arguments(
config=config_fixture,
config_url='https://example.com',
creds=creds_fixture,
silent=True,
dry_run=True,
script='execution_script',
mountpoint=Path('/tmp'),
skip_ntp=True,
skip_wkd=True,
skip_boot=True,
debug=True,
offline=True,
no_pkg_lookups=True,
plugin=Path('pytest_plugin.py'),
plugin_url=None,
skip_version_check=True,
advanced=True,
)
def test_config_file_parsing(
monkeypatch: MonkeyPatch,
config_fixture: Path,
creds_fixture: Path,
) -> None:
monkeypatch.setattr(
'sys.argv',
[
'archinstall',
'--config',
str(config_fixture),
'--creds',
str(creds_fixture),
],
)
handler = ArchConfigHandler()
arch_config = handler.config
# TODO: Use the real values from the test fixture instead of clearing out the entries
arch_config.disk_config.device_modifications = [] # type: ignore[union-attr]
assert arch_config == ArchConfig(
version=version('archinstall'),
script='test_script',
app_config=ApplicationConfiguration(
bluetooth_config=BluetoothConfiguration(enabled=True),
audio_config=AudioConfiguration(audio=Audio.PIPEWIRE),
print_service_config=PrintServiceConfiguration(enabled=True),
),
auth_config=AuthenticationConfiguration(
root_enc_password=Password(enc_password='password_hash'),
users=[
User(
username='user_name',
password=Password(enc_password='password_hash'),
sudo=True,
groups=['wheel'],
),
],
u2f_config=U2FLoginConfiguration(
u2f_login_method=U2FLoginMethod.Passwordless,
passwordless_sudo=True,
),
),
locale_config=LocaleConfiguration(
kb_layout='us',
sys_lang='en_US',
sys_enc='UTF-8',
),
archinstall_language=translation_handler.get_language_by_abbr('en'),
disk_config=DiskLayoutConfiguration(
config_type=DiskLayoutType.Default,
device_modifications=[],
lvm_config=None,
mountpoint=None,
),
profile_config=ProfileConfiguration(
profile=profile_handler.parse_profile_config(
{
'custom_settings': {
'Hyprland': {
CustomSetting.SeatAccess: 'polkit',
},
'Sway': {
CustomSetting.SeatAccess: 'seatd',
},
'KDE Plasma': {
CustomSetting.PlasmaFlavor: 'plasma-meta',
},
},
'details': [
'Sway',
'Hyprland',
],
'main': 'Desktop',
}
),
gfx_driver=GfxDriver.AllOpenSource,
greeter=GreeterType.Lightdm,
),
mirror_config=MirrorConfiguration(
mirror_regions=[
MirrorRegion(
name='Australia',
urls=['http://archlinux.mirror.digitalpacific.com.au/$repo/os/$arch'],
),
],
custom_servers=[CustomServer('https://mymirror.com/$repo/os/$arch')],
optional_repositories=[Repository.Testing],
custom_repositories=[
CustomRepository(
name='myrepo',
url='https://myrepo.com/$repo/os/$arch',
sign_check=SignCheck.Required,
sign_option=SignOption.TrustAll,
),
],
),
network_config=NetworkConfiguration(
type=NicType.MANUAL,
nics=[
Nic(
iface='eno1',
ip='192.168.1.15/24',
dhcp=True,
gateway='192.168.1.1',
dns=[
'192.168.1.1',
'9.9.9.9',
],
),
],
),
bootloader_config=BootloaderConfiguration(
bootloader=Bootloader.Systemd,
uki=False,
removable=False,
),
hostname='archy',
kernels=['linux-zen'],
ntp=True,
packages=['firefox'],
pacman_config=PacmanConfiguration(parallel_downloads=66),
swap=ZramConfiguration(enabled=False),
timezone='UTC',
services=['service_1', 'service_2'],
custom_commands=["echo 'Hello, World!'"],
)
def test_deprecated_mirror_config_parsing(
monkeypatch: MonkeyPatch,
deprecated_mirror_config: Path,
) -> None:
monkeypatch.setattr(
'sys.argv',
[
'archinstall',
'--config',
str(deprecated_mirror_config),
],
)
handler = ArchConfigHandler()
arch_config = handler.config
assert arch_config.mirror_config == MirrorConfiguration(
mirror_regions=[
MirrorRegion(
name='Australia',
urls=['http://archlinux.mirror.digitalpacific.com.au/$repo/os/$arch'],
),
],
custom_servers=[],
optional_repositories=[Repository.Testing],
custom_repositories=[
CustomRepository(
name='my_mirror',
url='example.com',
sign_check=SignCheck.Optional,
sign_option=SignOption.TrustedOnly,
),
],
)
def test_deprecated_creds_config_parsing(
monkeypatch: MonkeyPatch,
deprecated_creds_config: Path,
) -> None:
monkeypatch.setattr(
'sys.argv',
[
'archinstall',
'--creds',
str(deprecated_creds_config),
],
)
handler = ArchConfigHandler()
arch_config = handler.config
assert arch_config.auth_config is not None
assert arch_config.auth_config.root_enc_password == Password(plaintext='rootPwd')
assert arch_config.auth_config.users == [
User(
username='user_name',
password=Password(plaintext='userPwd'),
sudo=True,
groups=['wheel'],
),
]
def test_deprecated_audio_config_parsing(
monkeypatch: MonkeyPatch,
deprecated_audio_config: Path,
) -> None:
monkeypatch.setattr(
'sys.argv',
[
'archinstall',
'--config',
str(deprecated_audio_config),
],
)
handler = ArchConfigHandler()
arch_config = handler.config
assert arch_config.app_config == ApplicationConfiguration(
audio_config=AudioConfiguration(audio=Audio.PIPEWIRE),
)
def test_encrypted_creds_with_arg(
monkeypatch: MonkeyPatch,
encrypted_creds_fixture: Path,
) -> None:
monkeypatch.setattr(
'sys.argv',
[
'archinstall',
'--creds',
str(encrypted_creds_fixture),
'--creds-decryption-key',
'master',
],
)
handler = ArchConfigHandler()
arch_config = handler.config
assert arch_config.auth_config is not None
assert arch_config.auth_config.root_enc_password == Password(enc_password='$y$j9T$FWCInXmSsS.8KV4i7O50H.$Hb6/g.Sw1ry888iXgkVgc93YNuVk/Rw94knDKdPVQw7')
assert arch_config.auth_config.users == [
User(
username='t',
password=Password(enc_password='$y$j9T$3KxMigAEnjtzbjalhLewE.$gmuoQtc9RNY/PmO/GxHHYvkZNO86Eeftg1Oc7L.QSO/'),
sudo=True,
groups=[],
),
]
def test_encrypted_creds_with_env_var(
monkeypatch: MonkeyPatch,
encrypted_creds_fixture: Path,
) -> None:
os.environ['ARCHINSTALL_CREDS_DECRYPTION_KEY'] = 'master'
monkeypatch.setattr(
'sys.argv',
[
'archinstall',
'--creds',
str(encrypted_creds_fixture),
],
)
handler = ArchConfigHandler()
arch_config = handler.config
assert arch_config.auth_config is not None
assert arch_config.auth_config.root_enc_password == Password(enc_password='$y$j9T$FWCInXmSsS.8KV4i7O50H.$Hb6/g.Sw1ry888iXgkVgc93YNuVk/Rw94knDKdPVQw7')
assert arch_config.auth_config.users == [
User(
username='t',
password=Password(enc_password='$y$j9T$3KxMigAEnjtzbjalhLewE.$gmuoQtc9RNY/PmO/GxHHYvkZNO86Eeftg1Oc7L.QSO/'),
sudo=True,
groups=[],
),
]
def test_example_config_parsing(
monkeypatch: MonkeyPatch,
example_config_fixture: Path,
example_creds_fixture: Path,
) -> None:
monkeypatch.setattr(
'sys.argv',
[
'archinstall',
'--config',
str(example_config_fixture),
'--creds',
str(example_creds_fixture),
],
)
handler = ArchConfigHandler()
arch_config = handler.config
assert arch_config.disk_config is not None
assert arch_config.profile_config is not None
assert arch_config.auth_config is not None
assert arch_config.auth_config.users
def test_example_config_partitions(example_config_fixture: Path) -> None:
# partition entries are only parsed when the configured device is present on
# the machine, which is never the case in CI, so read them here directly
config = json.loads(example_config_fixture.read_text())
device_modifications = config['disk_config']['device_modifications']
assert device_modifications
for device in device_modifications:
partitions = device['partitions']
assert partitions
previous_end = None
for partition in partitions:
assert 'dev_path' in partition
start = Size.parse_args(partition['start'])
end = start + Size.parse_args(partition['size'])
assert start.is_valid_start()
if previous_end is not None:
assert start >= previous_end
previous_end = end