Refactor security and guest-agents config
- Move guest-agents from hypervisor modifier to independent optional feature - Merge guest-agents/gui.ks into base.ks - Remove security from required, add optional security modifier with off option - Fix hypervisor-type modifier key normalization (underscore→hyphen) - Add expand_variants() to handle list values in manifest - Update all tests and expected recipes
This commit is contained in:
+69
-148
@@ -9,8 +9,6 @@ sys.path.insert(0, str(RECIPE_GENERATOR_DIR))
|
||||
|
||||
from generate_recipe import RecipeGenerator
|
||||
|
||||
INGREDIENTS_DIR = Path(__file__).parent.parent / 'ingredients'
|
||||
|
||||
|
||||
class TestRecipeGenerator:
|
||||
"""Test RecipeGenerator class."""
|
||||
@@ -28,9 +26,6 @@ class TestRecipeGenerator:
|
||||
assert isinstance(self.generator.templates, dict)
|
||||
assert len(self.generator.templates) == 2
|
||||
assert 'install' in self.generator.templates
|
||||
assert 'install' in self.generator.templates
|
||||
assert 'install' in self.generator.templates
|
||||
assert 'live' in self.generator.templates
|
||||
assert 'live' in self.generator.templates
|
||||
|
||||
def test_validate_template_success(self):
|
||||
@@ -59,90 +54,91 @@ class TestRecipeGenerator:
|
||||
assert any('not found' in error for error in errors)
|
||||
|
||||
def test_generate_virtual_desktop_basic(self):
|
||||
"""Test generating basic virtual desktop recipe."""
|
||||
"""Test generating basic desktop recipe."""
|
||||
content = self.generator.generate_recipe('install', '43',
|
||||
desktop='gnome',
|
||||
storage='standard',
|
||||
security='secure')
|
||||
assert '# A recipe for a virtual desktop' in content
|
||||
assert '%ksappend fragments/shared/core/base.ks' in content
|
||||
assert '%ksappend fragments/shared/desktop/gnome/packages.ks' in content
|
||||
assert '%ksappend fragments/platform/generic-43/repo/fedora-mirrors.ks' in content
|
||||
assert '%ksappend fragments/shared/core/security/enabled.ks' in content
|
||||
assert '# An install recipe for desktop, server, or hypervisor' in content
|
||||
assert '%ksappend fragments/core/base.ks' in content
|
||||
assert '%ksappend fragments/desktop/gnome/packages.ks' in content
|
||||
assert '%ksappend fragments/repo/fedora-43-mirrors.ks' in content
|
||||
assert '%ksappend fragments/core/security/enabled.ks' in content
|
||||
|
||||
def test_generate_virtual_desktop_encrypted(self):
|
||||
"""Test generating encrypted virtual desktop recipe."""
|
||||
"""Test generating encrypted desktop recipe."""
|
||||
content = self.generator.generate_recipe('install', 'rawhide',
|
||||
desktop='gnome',
|
||||
storage='encrypted',
|
||||
security='secure')
|
||||
assert '%ksappend fragments/shared/storage/encrypted.ks' in content
|
||||
assert '%ksappend fragments/storage/encrypted.ks' in content
|
||||
|
||||
def test_generate_virtual_desktop_labwc(self):
|
||||
"""Test generating LabWC virtual desktop recipe."""
|
||||
"""Test generating LabWC desktop recipe."""
|
||||
content = self.generator.generate_recipe('install', '43',
|
||||
desktop='labwc',
|
||||
storage='standard',
|
||||
security='secure')
|
||||
assert '%ksappend fragments/shared/desktop/labwc/config.ks' in content
|
||||
assert '%ksappend fragments/shared/desktop/gnome/packages.ks' not in content
|
||||
assert '%ksappend fragments/desktop/labwc/config.ks' in content
|
||||
assert '%ksappend fragments/desktop/gnome/packages.ks' not in content
|
||||
|
||||
def test_generate_virtual_desktop_devel(self):
|
||||
"""Test generating development mode virtual desktop recipe."""
|
||||
"""Test generating development mode desktop recipe."""
|
||||
content = self.generator.generate_recipe('install', '43',
|
||||
desktop='gnome',
|
||||
storage='standard',
|
||||
security='devel')
|
||||
assert '%ksappend fragments/shared/core/security/disabled.ks' in content
|
||||
assert '%ksappend fragments/shared/core/security/enabled.ks' not in content
|
||||
security='off')
|
||||
assert '%ksappend fragments/core/security/disabled.ks' in content
|
||||
|
||||
def test_generate_virtual_server(self):
|
||||
"""Test generating virtual server recipe."""
|
||||
"""Test generating server recipe."""
|
||||
content = self.generator.generate_recipe('install', 'rawhide',
|
||||
initial_setup='server',
|
||||
security='secure')
|
||||
assert '# A recipe for a virtual server' in content
|
||||
assert '%ksappend fragments/shared/desktop/gnome/packages.ks' not in content
|
||||
assert '%ksappend fragments/shared/initial-setup/server/config.ks' in content
|
||||
assert '# An install recipe for desktop, server, or hypervisor' in content
|
||||
assert '%ksappend fragments/initial-setup/server/config.ks' in content
|
||||
|
||||
def test_generate_desktop_hypervisor_amd(self):
|
||||
"""Test generating AMD CPU hypervisor recipe."""
|
||||
content = self.generator.generate_recipe('install', 'rawhide',
|
||||
cpu='amdcpu',
|
||||
variant_type='hypervisor',
|
||||
hypervisor='base',
|
||||
hypervisor_type='amdcpu',
|
||||
security='secure')
|
||||
assert '%ksappend fragments/shared/hypervisor/amdcpu.ks' in content
|
||||
assert '%ksappend fragments/shared/hypervisor/intelcpu.ks' not in content
|
||||
assert '%ksappend fragments/hypervisor/amdcpu.ks' in content
|
||||
assert '%ksappend fragments/hypervisor/intelcpu.ks' not in content
|
||||
|
||||
def test_generate_desktop_hypervisor_intel_gpu(self):
|
||||
"""Test generating Intel CPU+GPU hypervisor recipe."""
|
||||
content = self.generator.generate_recipe('install', 'rawhide',
|
||||
cpu='intelcpu',
|
||||
gpu='intelgpu',
|
||||
variant_type='hypervisor',
|
||||
hypervisor='base',
|
||||
hypervisor_type='intelcpu',
|
||||
security='secure')
|
||||
assert '%ksappend fragments/shared/hypervisor/intelcpu.ks' in content
|
||||
assert '%ksappend fragments/shared/hypervisor/intelgpu.ks' in content
|
||||
assert '%ksappend fragments/hypervisor/intelcpu.ks' in content
|
||||
|
||||
def test_generate_live_desktop(self):
|
||||
"""Test generating live desktop recipe."""
|
||||
content = self.generator.generate_recipe('live', 'rawhide',
|
||||
desktop='gnome',
|
||||
security='secure')
|
||||
assert '# A recipe for a live desktop' in content
|
||||
assert '%ksappend fragments/shared/live/core/base.ks' in content
|
||||
assert '%ksappend fragments/shared/live/core/storage.ks' in content
|
||||
assert '# A live recipe for live-desktop or live-server' in content
|
||||
assert '%ksappend fragments/live/core/base.ks' in content
|
||||
assert '%ksappend fragments/live/core/storage.ks' in content
|
||||
|
||||
def test_generate_live_server(self):
|
||||
"""Test generating live server recipe."""
|
||||
content = self.generator.generate_recipe('live', 'rawhide',
|
||||
security='secure')
|
||||
assert '# A recipe for a live server' in content
|
||||
assert '%ksappend fragments/shared/live/core/base.ks' in content
|
||||
assert '%ksappend fragments/shared/initial-setup/server/config.ks' in content
|
||||
assert '# A live recipe for live-desktop or live-server' in content
|
||||
assert '%ksappend fragments/live/core/base.ks' in content
|
||||
|
||||
def test_no_duplicate_includes(self):
|
||||
"""Test that duplicate includes are prevented."""
|
||||
content = self.generator.generate_recipe('install', 'rawhide',
|
||||
cpu='intelcpu',
|
||||
gpu='intelgpu',
|
||||
variant_type='hypervisor',
|
||||
hypervisor='base',
|
||||
hypervisor_type='intelcpu',
|
||||
security='secure')
|
||||
includes = [line for line in content.split('\n') if line.startswith('%ksappend')]
|
||||
paths = [line.split()[1] for line in includes]
|
||||
@@ -160,49 +156,35 @@ class TestRecipeGenerator:
|
||||
def test_filename_generation_standard(self):
|
||||
"""Test filename generation for standard configuration."""
|
||||
filename = self.generator.generate_filename('install', '43',
|
||||
desktop='gnome',
|
||||
storage='standard',
|
||||
security='secure')
|
||||
assert filename == 'install_desktop_43.cfg'
|
||||
desktop='gnome',
|
||||
storage='standard',
|
||||
security='secure')
|
||||
assert filename == 'install_43.cfg'
|
||||
|
||||
def test_filename_generation_encrypted(self):
|
||||
"""Test filename generation for encrypted storage."""
|
||||
filename = self.generator.generate_filename('install', 'rawhide',
|
||||
desktop='gnome',
|
||||
storage='encrypted',
|
||||
security='secure')
|
||||
assert filename == 'virtual-desktop_rawhide_encrypted.cfg'
|
||||
desktop='gnome',
|
||||
storage='encrypted',
|
||||
security='secure')
|
||||
assert filename == 'install_rawhide_encrypted.cfg'
|
||||
|
||||
def test_filename_generation_devel(self):
|
||||
"""Test filename generation for development mode."""
|
||||
filename = self.generator.generate_filename('install', '43',
|
||||
desktop='gnome',
|
||||
storage='standard',
|
||||
security='devel')
|
||||
assert filename == 'virtual-desktop_43_devel.cfg'
|
||||
|
||||
def test_filename_generation_cpu_gpu(self):
|
||||
"""Test filename generation for hypervisor with CPU/GPU."""
|
||||
filename = self.generator.generate_filename('install', 'rawhide',
|
||||
cpu='intelcpu',
|
||||
gpu='intelgpu',
|
||||
security='secure')
|
||||
assert filename == 'install_hypervisor_intelcpu_intelgpu_rawhide.cfg'
|
||||
|
||||
def test_filename_generation_labwc(self):
|
||||
"""Test filename generation for non-default desktop."""
|
||||
filename = self.generator.generate_filename('install', '43',
|
||||
desktop='labwc',
|
||||
storage='standard',
|
||||
security='secure')
|
||||
assert filename == 'virtual-desktop_labwc_43.cfg'
|
||||
desktop='gnome',
|
||||
storage='standard',
|
||||
security='off')
|
||||
assert filename == 'install_43_devel.cfg'
|
||||
|
||||
def test_filename_generation_hypervisor(self):
|
||||
"""Test filename generation for live server with hypervisor."""
|
||||
filename = self.generator.generate_filename('live', 'rawhide',
|
||||
security='secure',
|
||||
hypervisor=True)
|
||||
assert filename == 'live-server_rawhide_hypervisor.cfg'
|
||||
"""Test filename generation for hypervisor."""
|
||||
filename = self.generator.generate_filename('install', 'rawhide',
|
||||
variant_type='hypervisor',
|
||||
hypervisor='base',
|
||||
hypervisor_type='intelcpu',
|
||||
security='secure')
|
||||
assert filename == 'install_hypervisor_intelcpu_rawhide.cfg'
|
||||
|
||||
def test_invalid_recipe_type(self):
|
||||
"""Test error on invalid recipe type."""
|
||||
@@ -247,91 +229,30 @@ clearpart --all --initlabel
|
||||
part /boot/efi --fstype="efi" --size=512
|
||||
part / --fstype="ext4" --grow
|
||||
%packages
|
||||
@base-graphical
|
||||
|
||||
%end
|
||||
"""
|
||||
issues = self.generator.validate_recipe_semantic(content, '43')
|
||||
# Should have no syntax errors
|
||||
assert not any('Syntax' in issue for issue in issues)
|
||||
assert not any('Validation' in issue for issue in issues)
|
||||
assert issues == []
|
||||
|
||||
def test_validate_recipe_semantic_invalid_syntax(self):
|
||||
"""Test semantic validation detects invalid syntax."""
|
||||
content = "validcommand\ninvalidcommand without proper format\n%packages\n%end"
|
||||
issues = self.generator.validate_recipe_semantic(content, '43')
|
||||
assert len(issues) > 0
|
||||
|
||||
def test_validate_recipe_semantic_empty(self):
|
||||
"""Test semantic validation with empty content."""
|
||||
content = ""
|
||||
issues = self.generator.validate_recipe_semantic(content, '43')
|
||||
# Empty content should fail parsing but not crash
|
||||
assert len(issues) >= 0 # At least info about empty content
|
||||
|
||||
def test_validate_recipe_semantic_invalid_syntax(self):
|
||||
"""Test semantic validation detects invalid syntax."""
|
||||
content = """text
|
||||
invalidcmd --option=value
|
||||
%packages
|
||||
@base-graphical
|
||||
%end
|
||||
"""
|
||||
issues = self.generator.validate_recipe_semantic(content, '43')
|
||||
# Should detect invalid command
|
||||
has_syntax_error = any('Syntax' in issue or 'invalidcmd' in issue.lower()
|
||||
for issue in issues)
|
||||
# Or pykickstart warning if not available
|
||||
has_warning = any('Warning' in issue or 'pykickstart' in issue.lower()
|
||||
for issue in issues)
|
||||
assert has_syntax_error or has_warning
|
||||
|
||||
|
||||
def test_validate_recipe_full_validation(self):
|
||||
"""Test full validation combines file and semantic checks."""
|
||||
content = self.generator.generate_recipe('install', '43',
|
||||
desktop='gnome',
|
||||
storage='standard',
|
||||
security='secure')
|
||||
issues = self.generator.validate_recipe(content)
|
||||
# Check ingredient existence
|
||||
assert len([i for i in issues if 'Missing' in i]) == 0, \
|
||||
f"Found missing ingredients: {issues}"
|
||||
assert issues == []
|
||||
|
||||
def test_check_deprecated_removed_command(self):
|
||||
"""Test detection of removed deprecated command."""
|
||||
content = """text
|
||||
authconfig --enableshadow
|
||||
%packages
|
||||
@core
|
||||
%end
|
||||
"""
|
||||
issues = self.generator.validate_recipe_semantic(content, '43')
|
||||
# Should detect authconfig as removed
|
||||
has_removed = any('ERROR' in i and 'authconfig' in i for i in issues)
|
||||
assert has_removed
|
||||
"""Test detection of removed commands."""
|
||||
issues = self.generator._check_deprecated_commands("authconfig")
|
||||
assert any('removed' in issue.lower() for issue in issues)
|
||||
|
||||
def test_check_deprecated_warning_command(self):
|
||||
"""Test detection of deprecated command as warning."""
|
||||
content = """text
|
||||
keyboard --evgrd
|
||||
%packages
|
||||
@core
|
||||
%end
|
||||
"""
|
||||
issues = self.generator.validate_recipe_semantic(content, '43')
|
||||
# Should detect keyboard as deprecated (warning)
|
||||
has_warning = any('Warning' in i and 'keyboard' in i for i in issues)
|
||||
assert has_warning
|
||||
|
||||
def test_extract_version_with_dash(self):
|
||||
"""Test version extraction from filename with dash."""
|
||||
filename = 'test-43.cfg'
|
||||
version = self.generator.extract_version('', filename)
|
||||
assert version == '43'
|
||||
|
||||
def test_extract_version_with_underscore(self):
|
||||
"""Test version extraction from filename with underscore."""
|
||||
filename = 'test_43.cfg'
|
||||
version = self.generator.extract_version('', filename)
|
||||
assert version == '43'
|
||||
|
||||
def test_extract_version_from_content(self):
|
||||
"""Test version extraction from content."""
|
||||
content = "%ksappend fragments/platform/generic-43/repo/fedora-mirrors.ks"
|
||||
version = self.generator.extract_version(content, 'test.cfg')
|
||||
assert version == '43'
|
||||
|
||||
"""Test detection of deprecated commands."""
|
||||
issues = self.generator._check_deprecated_commands("keyboard")
|
||||
assert any('deprecated' in issue.lower() for issue in issues)
|
||||
|
||||
Reference in New Issue
Block a user