2018-05-09 00:38:54 +00:00
#
# Copyright (C) 2018 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from StringIO import StringIO
import unittest
2019-03-13 17:56:20 +00:00
from pylorax . api . compose import add_customizations , compose_types
2019-04-09 23:37:24 +00:00
from pylorax . api . compose import timezone_cmd , get_timezone_settings
2019-04-12 19:23:20 +00:00
from pylorax . api . compose import lang_cmd , get_languages , keyboard_cmd , get_keyboard_layout
2019-04-15 18:55:51 +00:00
from pylorax . api . compose import firewall_cmd , get_firewall_settings
2019-04-16 23:40:40 +00:00
from pylorax . api . compose import services_cmd , get_services , get_default_services
2019-04-09 23:37:24 +00:00
from pylorax . api . compose import get_kernel_append , bootloader_append , customize_ks_template
2018-05-09 00:38:54 +00:00
from pylorax . api . recipes import recipe_from_toml
2019-03-13 17:56:20 +00:00
from pylorax . sysutils import joinpaths
2018-05-09 00:38:54 +00:00
BASE_RECIPE = """ name = " test-cases "
description = " Used for testing "
version = " 0.0.1 "
"""
HOSTNAME = BASE_RECIPE + """ [customizations]
hostname = " testhostname "
"""
2019-04-09 23:37:24 +00:00
TIMEZONE = BASE_RECIPE + """ [customizations]
timezone = " US/Samoa "
"""
2018-05-09 00:38:54 +00:00
SSHKEY = BASE_RECIPE + """ [[customizations.sshkey]]
user = " root "
key = " ROOT SSH KEY "
"""
USER = BASE_RECIPE + """ [[customizations.user]]
name = " tester "
"""
2018-09-28 22:21:11 +00:00
ROOT_USER = BASE_RECIPE + """ [[customizations.user]]
name = " root "
"""
2018-05-09 00:38:54 +00:00
USER_KEY = """
2018-09-28 22:21:11 +00:00
key = " A SSH KEY FOR THE USER "
2018-05-09 00:38:54 +00:00
"""
USER_DESC = """
description = " a test user account "
"""
USER_CRYPT = """
password = " $6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31LeOUleVK/R/aeWVHVZDi26zAH.o0ywBKH9Tc0/wm7sW/q39uyd1 "
"""
USER_PLAIN = """
password = " plainpassword "
"""
USER_HOME = """
home = " /opt/users/tester/ "
"""
USER_SHELL = """
shell = " /usr/bin/zsh "
"""
USER_UID = """
uid = 1013
"""
USER_GID = """
gid = 4242
"""
USER_GROUPS = """
groups = [ " wheel " , " users " ]
"""
USER_ALL = USER + USER_KEY + USER_DESC + USER_CRYPT + USER_HOME + USER_SHELL + USER_UID + USER_GID
GROUP = BASE_RECIPE + """ [[customizations.group]]
name = " testgroup "
"""
GROUP_GID = GROUP + """
gid = 1011
"""
2018-05-09 18:20:24 +00:00
USER_GROUP = USER + """ [[customizations.group]]
name = " tester "
"""
2018-09-28 22:21:11 +00:00
KS_USER_ALL = ''' sshkey --user tester " A SSH KEY FOR THE USER "
2018-05-09 00:38:54 +00:00
user - - name tester - - homedir / opt / users / tester / - - iscrypted - - password " $6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31LeOUleVK/R/aeWVHVZDi26zAH.o0ywBKH9Tc0/wm7sW/q39uyd1 " - - shell / usr / bin / zsh - - uid 1013 - - gid 4242 - - gecos " a test user account "
'''
2018-09-28 22:21:11 +00:00
# ROOT TESTS
ROOT_CRYPT = ROOT_USER + USER_CRYPT
ROOT_PLAIN = ROOT_USER + USER_PLAIN
ROOT_CRYPT_KEY = ROOT_USER + USER_CRYPT + USER_KEY
ROOT_PLAIN_KEY = ROOT_USER + USER_PLAIN + USER_KEY
ROOT_KEY = ROOT_USER + USER_KEY
2018-05-09 00:38:54 +00:00
class CustomizationsTestCase ( unittest . TestCase ) :
def assertCustomization ( self , test , result ) :
r = recipe_from_toml ( test )
f = StringIO ( )
add_customizations ( f , r )
self . assertTrue ( result in f . getvalue ( ) , f . getvalue ( ) )
2018-05-09 18:20:24 +00:00
def assertNotCustomization ( self , test , result ) :
r = recipe_from_toml ( test )
f = StringIO ( )
add_customizations ( f , r )
self . assertTrue ( result not in f . getvalue ( ) , f . getvalue ( ) )
2018-05-09 00:38:54 +00:00
def test_set_hostname ( self ) :
""" Test setting the hostname """
self . assertCustomization ( HOSTNAME , " network --hostname=testhostname " )
def test_set_sshkey ( self ) :
""" Test setting sshkey without user """
self . assertCustomization ( SSHKEY , ' sshkey --user root " ROOT SSH KEY " ' )
def test_sshkey_only ( self ) :
""" Test adding a sshkey to an existing user account """
2018-09-28 22:21:11 +00:00
self . assertCustomization ( USER + USER_KEY , ' sshkey --user tester " A SSH KEY FOR THE USER " ' )
2018-05-09 00:38:54 +00:00
def test_create_user ( self ) :
""" Test creating a user with no options """
self . assertCustomization ( USER , " user --name tester " )
def test_create_user_desc ( self ) :
""" Test creating a user with a description """
self . assertCustomization ( USER + USER_DESC , ' --gecos " a test user account " ' )
def test_create_user_crypt ( self ) :
""" Test creating a user with a pre-crypted password """
self . assertCustomization ( USER + USER_CRYPT , ' --password " $6$CHO2$3r ' )
def test_create_user_plain ( self ) :
""" Test creating a user with a plaintext password """
self . assertCustomization ( USER + USER_PLAIN , ' --password " plainpassword " ' )
def test_create_user_home ( self ) :
""" Test creating user with a home directory """
self . assertCustomization ( USER + USER_HOME , " --homedir /opt/users/tester/ " )
def test_create_user_shell ( self ) :
""" Test creating user with shell set """
self . assertCustomization ( USER + USER_SHELL , " --shell /usr/bin/zsh " )
def test_create_user_uid ( self ) :
""" Test creating user with uid set """
self . assertCustomization ( USER + USER_UID , " --uid 1013 " )
def test_create_user_gid ( self ) :
""" Test creating user with gid set """
self . assertCustomization ( USER + USER_GID , " --gid 4242 " )
def test_create_user_groups ( self ) :
""" Test creating user with group membership """
self . assertCustomization ( USER + USER_GROUPS , " --groups wheel,users " )
2018-05-09 18:20:24 +00:00
def test_user_same_group ( self ) :
""" Test creating a group with the same name as a user """
# Creating a group with the same name should skip the group creation
self . assertCustomization ( USER_GROUP , " user --name tester " )
self . assertNotCustomization ( USER_GROUP , " group --name tester " )
2018-05-09 00:38:54 +00:00
def test_create_user_all ( self ) :
""" Test creating user with all settings """
r = recipe_from_toml ( USER_ALL )
f = StringIO ( )
add_customizations ( f , r )
self . assertEqual ( KS_USER_ALL , f . getvalue ( ) )
def test_create_group ( self ) :
""" Test creating group without gid set """
self . assertCustomization ( GROUP , " group --name testgroup " )
def test_create_group_gid ( self ) :
""" Test creating group with gid set """
self . assertCustomization ( GROUP_GID , " group --name testgroup --gid 1011 " )
2018-09-28 22:21:11 +00:00
def test_root_crypt ( self ) :
self . assertCustomization ( ROOT_CRYPT , ' rootpw --iscrypted " $6$CHO2$3r ' )
def test_root_plain ( self ) :
self . assertCustomization ( ROOT_PLAIN , ' rootpw --plaintext " plainpassword " ' )
def test_root_crypt_key ( self ) :
self . assertCustomization ( ROOT_CRYPT_KEY , ' rootpw --iscrypted " $6$CHO2$3r ' )
self . assertCustomization ( ROOT_CRYPT_KEY , ' sshkey --user root " A SSH KEY FOR THE USER " ' )
def test_root_plain_key ( self ) :
self . assertCustomization ( ROOT_PLAIN_KEY , ' rootpw --plaintext " plainpassword " ' )
self . assertCustomization ( ROOT_PLAIN_KEY , ' sshkey --user root " A SSH KEY FOR THE USER " ' )
2019-03-13 17:56:20 +00:00
self . assertNotCustomization ( ROOT_PLAIN_KEY , " rootpw --lock " )
2019-04-09 23:37:24 +00:00
def test_get_kernel_append ( self ) :
""" Test get_kernel_append function """
blueprint_data = """ name = " test-kernel "
description = " test recipe "
version = " 0.0.1 "
"""
blueprint2_data = blueprint_data + """
[ customizations . kernel ]
append = " nosmt=force "
"""
recipe = recipe_from_toml ( blueprint_data )
self . assertEqual ( get_kernel_append ( recipe ) , " " )
recipe = recipe_from_toml ( blueprint2_data )
self . assertEqual ( get_kernel_append ( recipe ) , " nosmt=force " )
2019-03-13 17:56:20 +00:00
def test_bootloader_append ( self ) :
""" Test bootloader_append function """
self . assertEqual ( bootloader_append ( " " , " nosmt=force " ) , ' bootloader --append= " nosmt=force " --location=none ' )
self . assertEqual ( bootloader_append ( " " , " nosmt=force console=ttyS0,115200n8 " ) ,
' bootloader --append= " nosmt=force console=ttyS0,115200n8 " --location=none ' )
self . assertEqual ( bootloader_append ( " bootloader --location=none " , " nosmt=force " ) ,
' bootloader --append= " nosmt=force " --location=none ' )
self . assertEqual ( bootloader_append ( " bootloader --location=none " , " console=ttyS0,115200n8 nosmt=force " ) ,
' bootloader --append= " console=ttyS0,115200n8 nosmt=force " --location=none ' )
self . assertEqual ( bootloader_append ( ' bootloader --append= " no_timer_check console=ttyS0,115200n8 " --location=mbr ' , " nosmt=force " ) ,
' bootloader --append= " no_timer_check console=ttyS0,115200n8 nosmt=force " --location=mbr ' )
self . assertEqual ( bootloader_append ( ' bootloader --append= " console=tty1 " --location=mbr --password= " BADPASSWORD " ' , " nosmt=force " ) ,
' bootloader --append= " console=tty1 nosmt=force " --location=mbr --password= " BADPASSWORD " ' )
2019-04-09 23:37:24 +00:00
def test_get_timezone_settings ( self ) :
""" Test get_timezone_settings function """
blueprint_data = """ name = " test-kernel "
description = " test recipe "
version = " 0.0.1 "
"""
blueprint2_data = blueprint_data + """
[ customizations . timezone ]
timezone = " US/Samoa "
"""
blueprint3_data = blueprint_data + """
[ customizations . timezone ]
ntpservers = [ " 0.north-america.pool.ntp.org " , " 1.north-america.pool.ntp.org " ]
"""
blueprint4_data = blueprint_data + """
[ customizations . timezone ]
timezone = " US/Samoa "
ntpservers = [ " 0.north-america.pool.ntp.org " , " 1.north-america.pool.ntp.org " ]
"""
recipe = recipe_from_toml ( blueprint_data )
self . assertEqual ( get_timezone_settings ( recipe ) , { } )
recipe = recipe_from_toml ( blueprint2_data )
self . assertEqual ( get_timezone_settings ( recipe ) , { " timezone " : " US/Samoa " } )
recipe = recipe_from_toml ( blueprint3_data )
self . assertEqual ( get_timezone_settings ( recipe ) ,
{ " ntpservers " : [ " 0.north-america.pool.ntp.org " , " 1.north-america.pool.ntp.org " ] } )
recipe = recipe_from_toml ( blueprint4_data )
self . assertEqual ( get_timezone_settings ( recipe ) ,
{ " timezone " : " US/Samoa " ,
" ntpservers " : [ " 0.north-america.pool.ntp.org " , " 1.north-america.pool.ntp.org " ] } )
2019-03-13 17:56:20 +00:00
2019-04-09 23:37:24 +00:00
def test_timezone_cmd ( self ) :
""" Test timezone_cmd function """
self . assertEqual ( timezone_cmd ( " timezone UTC " , { } ) , ' timezone UTC ' )
self . assertEqual ( timezone_cmd ( " timezone FOO " , { " timezone " : " US/Samoa " } ) ,
' timezone US/Samoa ' )
self . assertEqual ( timezone_cmd ( " timezone FOO " ,
{ " timezone " : " US/Samoa " , " ntpservers " : [ " 0.ntp.org " , " 1.ntp.org " ] } ) ,
' timezone US/Samoa --ntpservers=0.ntp.org,1.ntp.org ' )
self . assertEqual ( timezone_cmd ( " timezone --ntpservers=a,b,c FOO " ,
{ " timezone " : " US/Samoa " , " ntpservers " : [ " 0.pool.ntp.org " , " 1.pool.ntp.org " ] } ) ,
' timezone US/Samoa --ntpservers=0.pool.ntp.org,1.pool.ntp.org ' )
2019-04-12 19:23:20 +00:00
def test_get_languages ( self ) :
""" Test get_languages function """
blueprint_data = """ name = " test-locale "
description = " test recipe "
version = " 0.0.1 "
"""
blueprint2_data = blueprint_data + """
[ customizations . locale ]
languages = [ " en_CA.utf8 " , " en_HK.utf8 " ]
"""
blueprint3_data = blueprint_data + """
[ customizations . locale ]
keyboard = " de (dvorak) "
languages = [ " en_CA.utf8 " , " en_HK.utf8 " ]
"""
recipe = recipe_from_toml ( blueprint_data )
self . assertEqual ( get_languages ( recipe ) , [ ] )
recipe = recipe_from_toml ( blueprint2_data )
self . assertEqual ( get_languages ( recipe ) , [ " en_CA.utf8 " , " en_HK.utf8 " ] )
recipe = recipe_from_toml ( blueprint3_data )
self . assertEqual ( get_languages ( recipe ) , [ " en_CA.utf8 " , " en_HK.utf8 " ] )
def test_lang_cmd ( self ) :
""" Test lang_cmd function """
self . assertEqual ( lang_cmd ( " lang en_CA.utf8 " , { } ) , ' lang en_CA.utf8 ' )
self . assertEqual ( lang_cmd ( " lang en_US.utf8 " , [ " en_HK.utf8 " ] ) ,
' lang en_HK.utf8 ' )
self . assertEqual ( lang_cmd ( " lang en_US.utf8 " , [ " en_CA.utf8 " , " en_HK.utf8 " ] ) ,
' lang en_CA.utf8 --addsupport=en_HK.utf8 ' )
self . assertEqual ( lang_cmd ( " lang --addsupport en_US.utf8 en_CA.utf8 " ,
[ " en_CA.utf8 " , " en_HK.utf8 " , " en_GB.utf8 " ] ) ,
' lang en_CA.utf8 --addsupport=en_HK.utf8,en_GB.utf8 ' )
def test_get_keyboard_layout ( self ) :
""" Test get_keyboard_layout function """
blueprint_data = """ name = " test-locale "
description = " test recipe "
version = " 0.0.1 "
"""
blueprint2_data = blueprint_data + """
[ customizations . locale ]
keyboard = " de (dvorak) "
"""
blueprint3_data = blueprint_data + """
[ customizations . locale ]
keyboard = " de (dvorak) "
languages = [ " en_CA.utf8 " , " en_HK.utf8 " ]
"""
recipe = recipe_from_toml ( blueprint_data )
self . assertEqual ( get_keyboard_layout ( recipe ) , [ ] )
recipe = recipe_from_toml ( blueprint2_data )
self . assertEqual ( get_keyboard_layout ( recipe ) , " de (dvorak) " )
recipe = recipe_from_toml ( blueprint3_data )
self . assertEqual ( get_keyboard_layout ( recipe ) , " de (dvorak) " )
def test_keyboard_cmd ( self ) :
""" Test lang_cmd function """
self . assertEqual ( keyboard_cmd ( " keyboard us " , { } ) , " keyboard ' us ' " )
self . assertEqual ( keyboard_cmd ( " keyboard us " , " de (dvorak) " ) ,
" keyboard ' de (dvorak) ' " )
self . assertEqual ( keyboard_cmd ( " keyboard --vckeymap=us --xlayouts=us,gb " ,
" de (dvorak) " ) ,
" keyboard ' de (dvorak) ' " )
2019-04-15 18:55:51 +00:00
def test_get_firewall_settings ( self ) :
""" Test get_firewall_settings function """
blueprint_data = """ name = " test-firewall "
description = " test recipe "
version = " 0.0.1 "
"""
firewall_ports = """
[ customizations . firewall ]
ports = [ " 22:tcp " , " 80:tcp " , " imap:tcp " , " 53:tcp " , " 53:udp " ]
"""
firewall_services = """
[ customizations . firewall . services ]
enabled = [ " ftp " , " ntp " , " dhcp " ]
disabled = [ " telnet " ]
"""
blueprint2_data = blueprint_data + firewall_ports
blueprint3_data = blueprint_data + firewall_services
blueprint4_data = blueprint_data + firewall_ports + firewall_services
recipe = recipe_from_toml ( blueprint_data )
self . assertEqual ( get_firewall_settings ( recipe ) , { ' ports ' : [ ] , ' enabled ' : [ ] , ' disabled ' : [ ] } )
recipe = recipe_from_toml ( blueprint2_data )
self . assertEqual ( get_firewall_settings ( recipe ) ,
{ " ports " : [ " 22:tcp " , " 80:tcp " , " imap:tcp " , " 53:tcp " , " 53:udp " ] ,
" enabled " : [ ] , " disabled " : [ ] } )
recipe = recipe_from_toml ( blueprint3_data )
self . assertEqual ( get_firewall_settings ( recipe ) ,
{ " ports " : [ ] ,
" enabled " : [ " ftp " , " ntp " , " dhcp " ] , " disabled " : [ " telnet " ] } )
recipe = recipe_from_toml ( blueprint4_data )
self . assertEqual ( get_firewall_settings ( recipe ) ,
{ " ports " : [ " 22:tcp " , " 80:tcp " , " imap:tcp " , " 53:tcp " , " 53:udp " ] ,
" enabled " : [ " ftp " , " ntp " , " dhcp " ] , " disabled " : [ " telnet " ] } )
def test_firewall_cmd ( self ) :
""" Test firewall_cmd function """
self . assertEqual ( firewall_cmd ( " firewall --enabled " , { } ) , " firewall --enabled " )
self . assertEqual ( firewall_cmd ( " firewall --enabled " ,
{ " ports " : [ " 22:tcp " , " 80:tcp " , " imap:tcp " , " 53:tcp " , " 53:udp " ] ,
" enabled " : [ ] , " disabled " : [ ] } ) ,
2019-04-17 18:08:16 +00:00
" firewall --enabled --port=22:tcp,53:tcp,53:udp,80:tcp,imap:tcp " )
2019-04-15 18:55:51 +00:00
self . assertEqual ( firewall_cmd ( " firewall --enabled " ,
{ " ports " : [ " 22:tcp " , " 80:tcp " , " imap:tcp " , " 53:tcp " , " 53:udp " ] ,
" enabled " : [ " ftp " , " ntp " , " dhcp " ] , " disabled " : [ ] } ) ,
2019-04-17 18:08:16 +00:00
" firewall --enabled --port=22:tcp,53:tcp,53:udp,80:tcp,imap:tcp --service=dhcp,ftp,ntp " )
2019-04-15 18:55:51 +00:00
self . assertEqual ( firewall_cmd ( " firewall --enabled " ,
{ " ports " : [ " 22:tcp " , " 80:tcp " , " imap:tcp " , " 53:tcp " , " 53:udp " ] ,
" enabled " : [ " ftp " , " ntp " , " dhcp " ] , " disabled " : [ " telnet " ] } ) ,
2019-04-17 18:08:16 +00:00
" firewall --enabled --port=22:tcp,53:tcp,53:udp,80:tcp,imap:tcp --service=dhcp,ftp,ntp --remove-service=telnet " )
2019-04-15 18:55:51 +00:00
# Make sure that --disabled overrides setting ports and services
self . assertEqual ( firewall_cmd ( " firewall --disabled " ,
{ " ports " : [ " 22:tcp " , " 80:tcp " , " imap:tcp " , " 53:tcp " , " 53:udp " ] ,
" enabled " : [ " ftp " , " ntp " , " dhcp " ] , " disabled " : [ " telnet " ] } ) ,
" firewall --disabled " )
2019-04-17 18:08:16 +00:00
# Make sure that ports includes any existing settings from the firewall command
self . assertEqual ( firewall_cmd ( " firewall --enabled --port=8080:tcp --service=dns --remove-service=ftp " ,
{ " ports " : [ " 80:tcp " ] ,
" enabled " : [ " ntp " ] , " disabled " : [ " telnet " ] } ) ,
" firewall --enabled --port=8080:tcp,80:tcp --service=dns,ntp --remove-service=ftp,telnet " )
2019-04-15 18:55:51 +00:00
2019-04-16 23:40:40 +00:00
def test_get_services ( self ) :
""" Test get_services function """
blueprint_data = """ name = " test-services "
description = " test recipe "
version = " 0.0.1 "
[ customizations . services ]
"""
enable_services = """
enabled = [ " sshd " , " cockpit.socket " , " httpd " ]
"""
disable_services = """
disabled = [ " postfix " , " telnetd " ]
"""
blueprint2_data = blueprint_data + enable_services
blueprint3_data = blueprint_data + disable_services
blueprint4_data = blueprint_data + enable_services + disable_services
recipe = recipe_from_toml ( blueprint_data )
self . assertEqual ( get_services ( recipe ) , { ' enabled ' : [ ] , ' disabled ' : [ ] } )
recipe = recipe_from_toml ( blueprint2_data )
self . assertEqual ( get_services ( recipe ) ,
{ " enabled " : [ " cockpit.socket " , " httpd " , " sshd " ] , " disabled " : [ ] } )
recipe = recipe_from_toml ( blueprint3_data )
self . assertEqual ( get_services ( recipe ) ,
{ " enabled " : [ ] , " disabled " : [ " postfix " , " telnetd " ] } )
recipe = recipe_from_toml ( blueprint4_data )
self . assertEqual ( get_services ( recipe ) ,
{ " enabled " : [ " cockpit.socket " , " httpd " , " sshd " ] , " disabled " : [ " postfix " , " telnetd " ] } )
def test_services_cmd ( self ) :
""" Test services_cmd function """
self . assertEqual ( services_cmd ( " " , { " enabled " : [ ] , " disabled " : [ ] } ) , " " )
self . assertEqual ( services_cmd ( " " , { " enabled " : [ " cockpit.socket " , " httpd " , " sshd " ] , " disabled " : [ ] } ) ,
' services --enabled= " cockpit.socket,httpd,sshd " ' )
self . assertEqual ( services_cmd ( " " , { " enabled " : [ ] , " disabled " : [ " postfix " , " telnetd " ] } ) ,
' services --disabled= " postfix,telnetd " ' )
self . assertEqual ( services_cmd ( " " , { " enabled " : [ " cockpit.socket " , " httpd " , " sshd " ] ,
" disabled " : [ " postfix " , " telnetd " ] } ) ,
' services --disabled= " postfix,telnetd " --enabled= " cockpit.socket,httpd,sshd " ' )
self . assertEqual ( services_cmd ( " services --enabled=pop3 " , { " enabled " : [ " cockpit.socket " , " httpd " , " sshd " ] ,
" disabled " : [ " postfix " , " telnetd " ] } ) ,
' services --disabled= " postfix,telnetd " --enabled= " cockpit.socket,httpd,pop3,sshd " ' )
self . assertEqual ( services_cmd ( " services --disabled=imapd " , { " enabled " : [ " cockpit.socket " , " httpd " , " sshd " ] ,
" disabled " : [ " postfix " , " telnetd " ] } ) ,
' services --disabled= " imapd,postfix,telnetd " --enabled= " cockpit.socket,httpd,sshd " ' )
self . assertEqual ( services_cmd ( " services --enabled=pop3 --disabled=imapd " , { " enabled " : [ " cockpit.socket " , " httpd " , " sshd " ] ,
" disabled " : [ " postfix " , " telnetd " ] } ) ,
' services --disabled= " imapd,postfix,telnetd " --enabled= " cockpit.socket,httpd,pop3,sshd " ' )
def test_get_default_services ( self ) :
""" Test get_default_services function """
blueprint_data = """ name = " test-services "
description = " test recipe "
version = " 0.0.1 "
[ customizations . services ]
"""
enable_services = """
enabled = [ " sshd " , " cockpit.socket " , " httpd " ]
"""
disable_services = """
disabled = [ " postfix " , " telnetd " ]
"""
blueprint2_data = blueprint_data + enable_services
blueprint3_data = blueprint_data + disable_services
blueprint4_data = blueprint_data + enable_services + disable_services
recipe = recipe_from_toml ( blueprint_data )
self . assertEqual ( get_default_services ( recipe ) , " " )
recipe = recipe_from_toml ( blueprint2_data )
self . assertEqual ( get_default_services ( recipe ) , " services " )
recipe = recipe_from_toml ( blueprint3_data )
self . assertEqual ( get_default_services ( recipe ) , " services " )
recipe = recipe_from_toml ( blueprint4_data )
self . assertEqual ( get_default_services ( recipe ) , " services " )
2019-04-09 23:37:24 +00:00
def _checkBootloader ( self , result , append_str , line_limit = 0 ) :
""" Find the bootloader line and make sure append_str is in it """
# Optionally check to make sure the change is at the top of the template
line_num = 0
2019-03-13 17:56:20 +00:00
for line in result . splitlines ( ) :
if line . startswith ( " bootloader " ) and append_str in line :
2019-04-09 23:37:24 +00:00
if line_limit == 0 or line_num < line_limit :
return True
else :
print ( " FAILED: bootloader not in the first %d lines of the output " % line_limit )
return False
line_num + = 1
2019-03-13 17:56:20 +00:00
return False
2019-04-09 23:37:24 +00:00
def _checkTimezone ( self , result , settings , line_limit = 0 ) :
""" Find the timezone line and make sure it is as expected """
# Optionally check to make sure the change is at the top of the template
line_num = 0
for line in result . splitlines ( ) :
if line . startswith ( " timezone " ) :
if settings [ " timezone " ] in line and all ( [ True for n in settings [ " ntpservers " ] if n in line ] ) :
if line_limit == 0 or line_num < line_limit :
return True
else :
print ( " FAILED: timezone not in the first %d lines of the output " % line_limit )
return False
else :
print ( " FAILED: %s not matching %s " % ( settings , line ) )
line_num + = 1
return False
2019-04-12 19:23:20 +00:00
def _checkLang ( self , result , locales , line_limit = 0 ) :
""" Find the lang line and make sure it is as expected """
# Optionally check to make sure the change is at the top of the template
line_num = 0
for line in result . splitlines ( ) :
if line . startswith ( " lang " ) :
if all ( [ True for n in locales if n in line ] ) :
if line_limit == 0 or line_num < line_limit :
return True
else :
print ( " FAILED: lang not in the first %d lines of the output " % line_limit )
return False
else :
print ( " FAILED: %s not matching %s " % ( locales , line ) )
line_num + = 1
return False
def _checkKeyboard ( self , result , layout , line_limit = 0 ) :
""" Find the keyboard line and make sure it is as expected """
# Optionally check to make sure the change is at the top of the template
line_num = 0
for line in result . splitlines ( ) :
if line . startswith ( " keyboard " ) :
if layout in line :
if line_limit == 0 or line_num < line_limit :
return True
else :
print ( " FAILED: keyboard not in the first %d lines of the output " % line_limit )
return False
else :
print ( " FAILED: %s not matching %s " % ( layout , line ) )
line_num + = 1
return False
2019-04-15 18:55:51 +00:00
def _checkFirewall ( self , result , settings , line_limit = 0 ) :
""" Find the firewall line and make sure it is as expected """
# Optionally check to make sure the change is at the top of the template
line_num = 0
for line in result . splitlines ( ) :
if line . startswith ( " firewall " ) :
# First layout is used twice, so total count should be n+1
ports = all ( [ bool ( p in line ) for p in settings [ " ports " ] ] )
enabled = all ( [ bool ( e in line ) for e in settings [ " enabled " ] ] )
disabled = all ( [ bool ( d in line ) for d in settings [ " disabled " ] ] )
if ports and enabled and disabled :
if line_limit == 0 or line_num < line_limit :
return True
else :
print ( " FAILED: firewall not in the first %d lines of the output " % line_limit )
return False
else :
print ( " FAILED: %s not matching %s " % ( settings , line ) )
line_num + = 1
return False
2019-04-16 23:40:40 +00:00
def _checkServices ( self , result , settings , line_limit = 0 ) :
""" Find the services line and make sure it is as expected """
# Optionally check to make sure the change is at the top of the template
line_num = 0
for line in result . splitlines ( ) :
if line . startswith ( " services " ) :
# First layout is used twice, so total count should be n+1
enabled = all ( [ bool ( e in line ) for e in settings [ " enabled " ] ] )
disabled = all ( [ bool ( d in line ) for d in settings [ " disabled " ] ] )
if enabled and disabled :
if line_limit == 0 or line_num < line_limit :
return True
else :
print ( " FAILED: services not in the first %d lines of the output " % line_limit )
return False
else :
print ( " FAILED: %s not matching %s " % ( settings , line ) )
line_num + = 1
return False
2019-04-09 23:37:24 +00:00
def test_template_defaults ( self ) :
""" Test that customize_ks_template includes defaults correctly """
blueprint_data = """ name = " test-kernel "
description = " test recipe "
version = " 0.0.1 "
[ [ packages ] ]
name = " lorax "
version = " * "
"""
recipe = recipe_from_toml ( blueprint_data )
# Make sure that a kickstart with no bootloader and no timezone has them added
result = customize_ks_template ( " firewall --enabled \n " , recipe )
print ( result )
self . assertEqual ( sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " bootloader " ) ] ) , 1 )
self . assertTrue ( self . _checkBootloader ( result , " none " , line_limit = 2 ) )
self . assertEqual ( sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " timezone " ) ] ) , 1 )
self . assertTrue ( self . _checkTimezone ( result , { " timezone " : " UTC " , " ntpservers " : [ ] } , line_limit = 2 ) )
2019-04-16 23:40:40 +00:00
self . assertTrue ( " services " not in result )
2019-04-09 23:37:24 +00:00
# Make sure that a kickstart with a bootloader, and no timezone has timezone added to the top
result = customize_ks_template ( " firewall --enabled \n bootloader --location=mbr \n " , recipe )
print ( result )
self . assertEqual ( sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " bootloader " ) ] ) , 1 )
self . assertTrue ( self . _checkBootloader ( result , " mbr " ) )
self . assertEqual ( sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " timezone " ) ] ) , 1 )
self . assertTrue ( self . _checkTimezone ( result , { " timezone " : " UTC " , " ntpservers " : [ ] } , line_limit = 1 ) )
2019-04-16 23:40:40 +00:00
self . assertTrue ( " services " not in result )
2019-04-09 23:37:24 +00:00
# Make sure that a kickstart with a bootloader and timezone has neither added
result = customize_ks_template ( " firewall --enabled \n bootloader --location=mbr \n timezone US/Samoa \n " , recipe )
print ( result )
self . assertEqual ( sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " bootloader " ) ] ) , 1 )
self . assertTrue ( self . _checkBootloader ( result , " mbr " ) )
self . assertEqual ( sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " timezone " ) ] ) , 1 )
self . assertTrue ( self . _checkTimezone ( result , { " timezone " : " US/Samoa " , " ntpservers " : [ ] } ) )
2019-04-16 23:40:40 +00:00
self . assertTrue ( " services " not in result )
2019-04-09 23:37:24 +00:00
def test_customize_ks_template ( self ) :
""" Test that customize_ks_template works correctly """
blueprint_data = """ name = " test-kernel "
description = " test recipe "
version = " 0.0.1 "
[ customizations . kernel ]
append = " nosmt=force "
[ customizations . timezone ]
timezone = " US/Samoa "
ntpservers = [ " 0.north-america.pool.ntp.org " , " 1.north-america.pool.ntp.org " ]
2019-04-12 19:23:20 +00:00
[ customizations . locale ]
keyboard = " de (dvorak) "
languages = [ " en_CA.utf8 " , " en_HK.utf8 " ]
2019-04-15 18:55:51 +00:00
[ customizations . firewall ]
ports = [ " 22:tcp " , " 80:tcp " , " imap:tcp " , " 53:tcp " , " 53:udp " ]
[ customizations . firewall . services ]
enabled = [ " ftp " , " ntp " , " dhcp " ]
disabled = [ " telnet " ]
2019-04-16 23:40:40 +00:00
[ customizations . services ]
enabled = [ " sshd " , " cockpit.socket " , " httpd " ]
disabled = [ " postfix " , " telnetd " ]
2019-04-09 23:37:24 +00:00
"""
tz_dict = { " timezone " : " US/Samoa " , " ntpservers " : [ " 0.north-america.pool.ntp.org " , " 1.north-america.pool.ntp.org " ] }
recipe = recipe_from_toml ( blueprint_data )
2019-03-13 17:56:20 +00:00
# Test against a kickstart without bootloader
result = customize_ks_template ( " firewall --enabled \n " , recipe )
2019-04-09 23:37:24 +00:00
self . assertTrue ( self . _checkBootloader ( result , " nosmt=force " , line_limit = 2 ) )
self . assertEqual ( sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " bootloader " ) ] ) , 1 )
self . assertTrue ( self . _checkTimezone ( result , tz_dict , line_limit = 2 ) )
self . assertEqual ( sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " timezone " ) ] ) , 1 )
2019-04-12 19:23:20 +00:00
self . assertTrue ( self . _checkLang ( result , [ " en_CA.utf8 " , " en_HK.utf8 " ] , line_limit = 4 ) )
self . assertEqual ( sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " lang " ) ] ) , 1 )
self . assertTrue ( self . _checkKeyboard ( result , " de (dvorak) " , line_limit = 4 ) )
self . assertEqual ( sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " keyboard " ) ] ) , 1 )
2019-04-15 18:55:51 +00:00
self . assertTrue ( self . _checkFirewall ( result ,
{ " ports " : [ " 22:tcp " , " 80:tcp " , " imap:tcp " , " 53:tcp " , " 53:udp " ] ,
" enabled " : [ " ftp " , " ntp " , " dhcp " ] , " disabled " : [ " telnet " ] } , line_limit = 6 ) )
self . assertEqual ( sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " firewall " ) ] ) , 1 )
2019-04-16 23:40:40 +00:00
self . assertTrue ( self . _checkServices ( result ,
{ " enabled " : [ " cockpit.socket " , " httpd " , " sshd " ] , " disabled " : [ " postfix " , " telnetd " ] } ,
line_limit = 8 ) )
self . assertEqual ( sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " services " ) ] ) , 1 )
2019-04-09 23:37:24 +00:00
# Test against a kickstart with a bootloader line
result = customize_ks_template ( " firewall --enabled \n bootloader --location=mbr \n " , recipe )
2019-03-13 17:56:20 +00:00
self . assertTrue ( self . _checkBootloader ( result , " nosmt=force " ) )
2019-04-09 23:37:24 +00:00
self . assertTrue ( self . _checkTimezone ( result , tz_dict , line_limit = 2 ) )
2019-03-13 17:56:20 +00:00
# Test against all of the available templates
share_dir = " ./share/ "
errors = [ ]
for compose_type in compose_types ( share_dir ) :
# Read the kickstart template for this type
ks_template_path = joinpaths ( share_dir , " composer " , compose_type ) + " .ks "
ks_template = open ( ks_template_path , " r " ) . read ( )
result = customize_ks_template ( ks_template , recipe )
if not self . _checkBootloader ( result , " nosmt=force " ) :
2019-04-09 23:37:24 +00:00
errors . append ( ( " bootloader for compose_type %s failed " % compose_type , result ) )
if sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " bootloader " ) ] ) != 1 :
errors . append ( ( " bootloader for compose_type %s failed: More than 1 entry " % compose_type , result ) )
# google images should retain their timezone settings
if compose_type == " google " :
if self . _checkTimezone ( result , tz_dict ) :
errors . append ( ( " timezone for compose_type %s failed " % compose_type , result ) )
elif not self . _checkTimezone ( result , tz_dict , line_limit = 2 ) :
# None of the templates have a timezone to modify, it should be placed at the top
errors . append ( ( " timezone for compose_type %s failed " % compose_type , result ) )
if sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " timezone " ) ] ) != 1 :
errors . append ( ( " timezone for compose_type %s failed: More than 1 entry " % compose_type , result ) )
2019-03-13 17:56:20 +00:00
2019-04-12 19:23:20 +00:00
if not self . _checkLang ( result , [ " en_CA.utf8 " , " en_HK.utf8 " ] ) :
errors . append ( ( " lang for compose_type %s failed " % compose_type , result ) )
if sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " lang " ) ] ) != 1 :
errors . append ( ( " lang for compose_type %s failed: More than 1 entry " % compose_type , result ) )
if not self . _checkKeyboard ( result , " de (dvorak) " ) :
errors . append ( ( " keyboard for compose_type %s failed " % compose_type , result ) )
if sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " keyboard " ) ] ) != 1 :
errors . append ( ( " keyboard for compose_type %s failed: More than 1 entry " % compose_type , result ) )
2019-04-15 18:55:51 +00:00
# google and openstack templates requires the firewall to be disabled
if compose_type == " google " or compose_type == " openstack " :
if not self . _checkFirewall ( result , { ' ports ' : [ ] , ' enabled ' : [ ] , ' disabled ' : [ ] } ) :
errors . append ( ( " firewall for compose_type %s failed " % compose_type , result ) )
else :
if not self . _checkFirewall ( result ,
{ " ports " : [ " 22:tcp " , " 80:tcp " , " imap:tcp " , " 53:tcp " , " 53:udp " ] ,
" enabled " : [ " ftp " , " ntp " , " dhcp " ] , " disabled " : [ " telnet " ] } ) :
errors . append ( ( " firewall for compose_type %s failed " % compose_type , result ) )
if sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " firewall " ) ] ) != 1 :
errors . append ( ( " firewall for compose_type %s failed: More than 1 entry " % compose_type , result ) )
2019-04-16 23:40:40 +00:00
if not self . _checkServices ( result ,
{ " enabled " : [ " cockpit.socket " , " httpd " , " sshd " ] ,
" disabled " : [ " postfix " , " telnetd " ] } ) :
errors . append ( ( " services for compose_type %s failed " % compose_type , result ) )
if sum ( [ 1 for l in result . splitlines ( ) if l . startswith ( " services " ) ] ) != 1 :
errors . append ( ( " services for compose_type %s failed: More than 1 entry " % compose_type , result ) )
2019-03-13 17:56:20 +00:00
# Print the bad results
for e , r in errors :
print ( " %s : \n %s \n \n " % ( e , r ) )
self . assertEqual ( errors , [ ] )