2018-04-30 18:34:48 +00:00
#
# Copyright (C) 2017 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/>.
#
import os
from pytoml import TomlError
import shutil
import tempfile
import unittest
2020-02-05 19:02:29 +00:00
from unittest import mock
2018-04-30 18:34:48 +00:00
import pylorax . api . recipes as recipes
2019-04-09 23:37:24 +00:00
from pylorax . api . compose import add_customizations , customize_ks_template
2018-04-30 18:34:48 +00:00
from pylorax . sysutils import joinpaths
2018-12-21 17:51:52 +00:00
from pykickstart . parser import KickstartParser
from pykickstart . version import makeVersion
2018-04-30 18:34:48 +00:00
class BasicRecipeTest ( unittest . TestCase ) :
@classmethod
def setUpClass ( self ) :
# Input toml is in .toml and python dict string is in .dict
input_recipes = [ ( " full-recipe.toml " , " full-recipe.dict " ) ,
( " minimal.toml " , " minimal.dict " ) ,
( " modules-only.toml " , " modules-only.dict " ) ,
2018-05-08 16:25:44 +00:00
( " packages-only.toml " , " packages-only.dict " ) ,
2018-07-11 18:07:45 +00:00
( " groups-only.toml " , " groups-only.dict " ) ,
2019-02-05 21:26:58 +00:00
( " custom-base.toml " , " custom-base.dict " ) ,
( " repos-git.toml " , " repos-git.dict " ) ]
2018-04-30 18:34:48 +00:00
results_path = " ./tests/pylorax/results/ "
2019-02-07 17:48:17 +00:00
self . input_toml = { }
2018-04-30 18:34:48 +00:00
for ( recipe_toml , recipe_dict ) in input_recipes :
with open ( joinpaths ( results_path , recipe_toml ) ) as f_toml :
with open ( joinpaths ( results_path , recipe_dict ) ) as f_dict :
# XXX Warning, can run arbitrary code
result_dict = eval ( f_dict . read ( ) )
2019-02-07 17:48:17 +00:00
self . input_toml [ recipe_toml ] = ( f_toml . read ( ) , result_dict )
2018-04-30 18:34:48 +00:00
2019-05-14 18:44:18 +00:00
# Used by diff tests
2018-04-30 18:34:48 +00:00
self . old_modules = [ recipes . RecipeModule ( " toml " , " 2.1 " ) ,
recipes . RecipeModule ( " bash " , " 4.* " ) ,
recipes . RecipeModule ( " httpd " , " 3.7.* " ) ]
self . new_modules = [ recipes . RecipeModule ( " toml " , " 2.1 " ) ,
recipes . RecipeModule ( " httpd " , " 3.8.* " ) ,
recipes . RecipeModule ( " openssh " , " 2.8.1 " ) ]
self . modules_result = [ { " new " : { " Modules " : { " version " : " 2.8.1 " , " name " : " openssh " } } ,
" old " : None } ,
{ " new " : None ,
" old " : { " Modules " : { " name " : " bash " , " version " : " 4.* " } } } ,
{ " new " : { " Modules " : { " version " : " 3.8.* " , " name " : " httpd " } } ,
" old " : { " Modules " : { " version " : " 3.7.* " , " name " : " httpd " } } } ]
2019-05-14 18:44:18 +00:00
self . old_packages = [ recipes . RecipePackage ( " python " , " 2.7.* " ) ,
recipes . RecipePackage ( " parted " , " 3.2 " ) ]
self . new_packages = [ recipes . RecipePackage ( " python " , " 2.7.* " ) ,
recipes . RecipePackage ( " parted " , " 3.2 " ) ,
recipes . RecipePackage ( " git " , " 2.13.* " ) ]
2018-04-30 18:34:48 +00:00
self . packages_result = [ { " new " : { " Packages " : { " name " : " git " , " version " : " 2.13.* " } } , " old " : None } ]
2019-05-14 18:44:18 +00:00
self . old_groups = [ recipes . RecipeGroup ( " backup-client " ) ,
recipes . RecipeGroup ( " standard " ) ]
self . new_groups = [ recipes . RecipeGroup ( " console-internet " ) ,
recipes . RecipeGroup ( " standard " ) ]
2018-07-11 18:07:45 +00:00
self . groups_result = [ { ' new ' : { ' Groups ' : { ' name ' : ' console-internet ' } } , ' old ' : None } ,
{ ' new ' : None , ' old ' : { ' Groups ' : { ' name ' : ' backup-client ' } } } ]
2019-05-14 18:44:18 +00:00
# customizations test data and results.
self . old_custom = { ' hostname ' : ' custombase ' }
self . custom_sshkey1 = { ' sshkey ' : [ { ' user ' : ' root ' , ' key ' : ' A SSH KEY FOR ROOT ' } ] }
self . custom_sshkey2 = { ' sshkey ' : [ { ' user ' : ' root ' , ' key ' : ' A DIFFERENT SSH KEY FOR ROOT ' } ] }
self . custom_sshkey3 = { ' sshkey ' : [ { ' user ' : ' root ' , ' key ' : ' A SSH KEY FOR ROOT ' } , { ' user ' : ' cliff ' , ' key ' : ' A SSH KEY FOR CLIFF ' } ] }
self . custom_kernel = { ' kernel ' : { ' append ' : ' nosmt=force ' } }
self . custom_user1 = { ' user ' : [ { ' name ' : ' admin ' , ' description ' : ' Administrator account ' , ' password ' : ' $6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31L... ' , ' key ' : ' PUBLIC SSH KEY ' , ' home ' : ' /srv/widget/ ' , ' shell ' : ' /usr/bin/bash ' , ' groups ' : [ ' widget ' , ' users ' , ' wheel ' ] , ' uid ' : 1200 , ' gid ' : 1200 } ] }
self . custom_user2 = { ' user ' : [ { ' name ' : ' admin ' , ' description ' : ' Administrator account ' , ' password ' : ' $6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31L... ' , ' key ' : ' PUBLIC SSH KEY ' , ' home ' : ' /root/ ' , ' shell ' : ' /usr/bin/bash ' , ' groups ' : [ ' widget ' , ' users ' , ' wheel ' ] , ' uid ' : 1200 , ' gid ' : 1200 } ] }
self . custom_user3 = { ' user ' : [ { ' name ' : ' admin ' , ' description ' : ' Administrator account ' , ' password ' : ' $6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31L... ' , ' key ' : ' PUBLIC SSH KEY ' , ' home ' : ' /srv/widget/ ' , ' shell ' : ' /usr/bin/bash ' , ' groups ' : [ ' widget ' , ' users ' , ' wheel ' ] , ' uid ' : 1200 , ' gid ' : 1200 } , { ' name ' : ' norman ' , ' key ' : ' PUBLIC SSH KEY ' } ] }
self . custom_group = { ' group ' : [ { ' name ' : ' widget ' , ' gid ' : 1130 } ] }
self . custom_timezone1 = { ' timezone ' : { ' timezone ' : ' US/Eastern ' , ' ntpservers ' : [ ' 0.north-america.pool.ntp.org ' , ' 1.north-america.pool.ntp.org ' ] } }
self . custom_timezone2 = { ' timezone ' : { ' timezone ' : ' US/Eastern ' } }
self . custom_timezone3 = { ' timezone ' : { ' ntpservers ' : [ ' 0.north-america.pool.ntp.org ' , ' 1.north-america.pool.ntp.org ' ] } }
self . custom_locale1 = { ' locale ' : { ' languages ' : [ ' en_US.UTF-8 ' ] , ' keyboard ' : ' us ' } }
self . custom_locale2 = { ' locale ' : { ' languages ' : [ ' en_US.UTF-8 ' ] } }
self . custom_locale3 = { ' locale ' : { ' keyboard ' : ' us ' } }
self . custom_firewall1 = { ' firewall ' : { ' ports ' : [ ' 22:tcp ' , ' 80:tcp ' , ' imap:tcp ' , ' 53:tcp ' , ' 53:udp ' ] , ' services ' : { ' enabled ' : [ ' ftp ' , ' ntp ' , ' dhcp ' ] , ' disabled ' : [ ' telnet ' ] } } }
self . custom_firewall2 = { ' firewall ' : { ' ports ' : [ ' 22:tcp ' , ' 80:tcp ' , ' imap:tcp ' , ' 53:tcp ' , ' 53:udp ' ] } }
self . custom_firewall3 = { ' firewall ' : { ' services ' : { ' enabled ' : [ ' ftp ' , ' ntp ' , ' dhcp ' ] , ' disabled ' : [ ' telnet ' ] } } }
self . custom_firewall4 = { ' firewall ' : { ' services ' : { ' enabled ' : [ ' ftp ' , ' ntp ' , ' dhcp ' ] } } }
self . custom_firewall5 = { ' firewall ' : { ' services ' : { ' disabled ' : [ ' telnet ' ] } } }
self . custom_services1 = { ' services ' : { ' enabled ' : [ ' sshd ' , ' cockpit.socket ' , ' httpd ' ] , ' disabled ' : [ ' postfix ' , ' telnetd ' ] } }
self . custom_services2 = { ' services ' : { ' enabled ' : [ ' sshd ' , ' cockpit.socket ' , ' httpd ' ] } }
self . custom_services3 = { ' services ' : { ' disabled ' : [ ' postfix ' , ' telnetd ' ] } }
self . old_custom . update ( self . custom_sshkey1 )
# Build the new custom from these pieces
self . new_custom = self . old_custom . copy ( )
for d in [ self . custom_kernel , self . custom_user1 , self . custom_group , self . custom_timezone1 ,
self . custom_locale1 , self . custom_firewall1 , self . custom_services1 ] :
self . new_custom . update ( d )
self . custom_result = [ { ' new ' : { ' Customizations.firewall ' : { ' ports ' : [ ' 22:tcp ' , ' 80:tcp ' , ' imap:tcp ' , ' 53:tcp ' , ' 53:udp ' ] ,
' services ' : { ' disabled ' : [ ' telnet ' ] , ' enabled ' : [ ' ftp ' , ' ntp ' , ' dhcp ' ] } } } ,
' old ' : None } ,
{ ' new ' : { ' Customizations.group ' : [ { ' gid ' : 1130 , ' name ' : ' widget ' } ] } ,
' old ' : None } ,
{ ' new ' : { ' Customizations.kernel ' : { ' append ' : ' nosmt=force ' } } ,
' old ' : None } ,
{ ' new ' : { ' Customizations.locale ' : { ' keyboard ' : ' us ' , ' languages ' : [ ' en_US.UTF-8 ' ] } } ,
' old ' : None } ,
{ ' new ' : { ' Customizations.services ' : { ' disabled ' : [ ' postfix ' , ' telnetd ' ] , ' enabled ' : [ ' sshd ' , ' cockpit.socket ' , ' httpd ' ] } } ,
' old ' : None } ,
{ ' new ' : { ' Customizations.timezone ' : { ' ntpservers ' : [ ' 0.north-america.pool.ntp.org ' , ' 1.north-america.pool.ntp.org ' ] ,
' timezone ' : ' US/Eastern ' } } ,
' old ' : None } ,
{ ' new ' : { ' Customizations.user ' : [ { ' description ' : ' Administrator account ' , ' gid ' : 1200 ,
' groups ' : [ ' widget ' , ' users ' , ' wheel ' ] , ' home ' : ' /srv/widget/ ' ,
' key ' : ' PUBLIC SSH KEY ' , ' name ' : ' admin ' ,
' password ' : ' $6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31L... ' , ' shell ' : ' /usr/bin/bash ' , ' uid ' : 1200 } ] } ,
' old ' : None } ]
self . maxDiff = None
2018-04-30 18:34:48 +00:00
@classmethod
def tearDownClass ( self ) :
pass
def toml_to_recipe_test ( self ) :
""" Test converting the TOML string to a Recipe object """
2019-02-07 17:48:17 +00:00
for ( toml_str , recipe_dict ) in self . input_toml . values ( ) :
2018-04-30 18:34:48 +00:00
result = recipes . recipe_from_toml ( toml_str )
self . assertEqual ( result , recipe_dict )
def toml_to_recipe_fail_test ( self ) :
""" Test trying to convert a non-TOML string to a Recipe """
with self . assertRaises ( TomlError ) :
recipes . recipe_from_toml ( " This is not a TOML string \n " )
with self . assertRaises ( recipes . RecipeError ) :
recipes . recipe_from_toml ( ' name = " a failed toml string " \n ' )
def recipe_to_toml_test ( self ) :
""" Test converting a Recipe object to a TOML string """
# In order to avoid problems from matching strings we convert to TOML and
# then back so compare the Recipes.
2019-02-07 17:48:17 +00:00
for ( toml_str , _recipe_dict ) in self . input_toml . values ( ) :
2018-04-30 18:34:48 +00:00
# This is tested in toml_to_recipe
recipe_1 = recipes . recipe_from_toml ( toml_str )
# Convert the Recipe to TOML and then back to a Recipe
toml_2 = recipe_1 . toml ( )
recipe_2 = recipes . recipe_from_toml ( toml_2 )
self . assertEqual ( recipe_1 , recipe_2 )
def recipe_bump_version_test ( self ) :
""" Test the Recipe ' s version bump function """
# Neither have a version
2018-07-10 20:59:41 +00:00
recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , None , None , None , None )
2018-04-30 18:34:48 +00:00
new_version = recipe . bump_version ( None )
self . assertEqual ( new_version , " 0.0.1 " )
# Original has a version, new does not
2018-07-10 20:59:41 +00:00
recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , None , None , None , None )
2018-04-30 18:34:48 +00:00
new_version = recipe . bump_version ( " 0.0.1 " )
self . assertEqual ( new_version , " 0.0.2 " )
# Original has no version, new does
2018-07-10 20:59:41 +00:00
recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.0 " , None , None , None )
2018-04-30 18:34:48 +00:00
new_version = recipe . bump_version ( None )
self . assertEqual ( new_version , " 0.1.0 " )
# New and Original are the same
2018-07-10 20:59:41 +00:00
recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.0.1 " , None , None , None )
2018-04-30 18:34:48 +00:00
new_version = recipe . bump_version ( " 0.0.1 " )
self . assertEqual ( new_version , " 0.0.2 " )
# New is different from Original
2018-07-10 20:59:41 +00:00
recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , None , None , None )
2018-04-30 18:34:48 +00:00
new_version = recipe . bump_version ( " 0.0.1 " )
self . assertEqual ( new_version , " 0.1.1 " )
2019-05-14 18:44:18 +00:00
def find_field_test ( self ) :
""" Test the find_field_value function """
test_list = [ { " name " : " dog " } , { " name " : " cat " } , { " name " : " squirrel " } ]
self . assertEqual ( recipes . find_field_value ( " name " , " cat " , test_list ) , { " name " : " cat " } )
self . assertIsNone ( recipes . find_field_value ( " name " , " alien " , test_list ) )
self . assertIsNone ( recipes . find_field_value ( " color " , " green " , test_list ) )
self . assertIsNone ( recipes . find_field_value ( " color " , " green " , [ ] ) )
2018-04-30 18:34:48 +00:00
def find_name_test ( self ) :
""" Test the find_name function """
test_list = [ { " name " : " dog " } , { " name " : " cat " } , { " name " : " squirrel " } ]
self . assertEqual ( recipes . find_name ( " cat " , test_list ) , { " name " : " cat " } )
self . assertIsNone ( recipes . find_name ( " alien " , test_list ) )
2019-05-14 18:44:18 +00:00
self . assertIsNone ( recipes . find_name ( " alien " , [ ] ) )
def find_obj_test ( self ) :
""" Test the find_recipe_obj function """
test_recipe = { " customizations " : { " hostname " : " foo " , " users " : [ " root " ] } , " repos " : { " git " : [ " git-repos " ] } }
self . assertEqual ( recipes . find_recipe_obj ( [ " customizations " , " hostname " ] , test_recipe , " " ) , " foo " )
self . assertEqual ( recipes . find_recipe_obj ( [ " customizations " , " locale " ] , test_recipe , { } ) , { } )
self . assertEqual ( recipes . find_recipe_obj ( [ " repos " , " git " ] , test_recipe , " " ) , [ " git-repos " ] )
self . assertEqual ( recipes . find_recipe_obj ( [ " repos " , " git " , " oak " ] , test_recipe , " " ) , " " )
self . assertIsNone ( recipes . find_recipe_obj ( [ " pine " ] , test_recipe ) )
def diff_lists_test ( self ) :
""" Test the diff_lists function """
self . assertEqual ( recipes . diff_lists ( " Modules " , " name " , self . old_modules , self . old_modules ) , [ ] )
self . assertEqual ( recipes . diff_lists ( " Modules " , " name " , self . old_modules , self . new_modules ) , self . modules_result )
self . assertEqual ( recipes . diff_lists ( " Packages " , " name " , self . old_packages , self . new_packages ) , self . packages_result )
self . assertEqual ( recipes . diff_lists ( " Groups " , " name " , self . old_groups , self . new_groups ) , self . groups_result )
def customizations_diff_test ( self ) :
""" Test the customizations_diff function """
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = self . old_custom )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = self . new_custom )
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , self . custom_result )
def customizations_diff_services_test ( self ) :
""" Test the customizations_diff function with services variations """
# Test adding the services customization
old_custom = self . old_custom . copy ( )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = old_custom . copy ( )
new_custom . update ( self . custom_services1 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' new ' : { ' Customizations.services ' : { ' disabled ' : [ ' postfix ' , ' telnetd ' ] , ' enabled ' : [ ' sshd ' , ' cockpit.socket ' , ' httpd ' ] } } ,
' old ' : None } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
# Test removing disabled
old_custom = self . old_custom . copy ( )
old_custom . update ( self . custom_services1 )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = self . old_custom . copy ( )
new_custom . update ( self . custom_services2 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' old ' : { ' Customizations.services ' : { ' disabled ' : [ ' postfix ' , ' telnetd ' ] , ' enabled ' : [ ' sshd ' , ' cockpit.socket ' , ' httpd ' ] } } ,
' new ' : { ' Customizations.services ' : { ' enabled ' : [ ' sshd ' , ' cockpit.socket ' , ' httpd ' ] } } } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
# Test removing enabled
old_custom = self . old_custom . copy ( )
old_custom . update ( self . custom_services1 )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = self . old_custom . copy ( )
new_custom . update ( self . custom_services3 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' old ' : { ' Customizations.services ' : { ' disabled ' : [ ' postfix ' , ' telnetd ' ] , ' enabled ' : [ ' sshd ' , ' cockpit.socket ' , ' httpd ' ] } } ,
' new ' : { ' Customizations.services ' : { ' disabled ' : [ ' postfix ' , ' telnetd ' ] } } } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
def customizations_diff_firewall_test ( self ) :
""" Test the customizations_diff function with firewall variations """
# Test adding the firewall customization
old_custom = self . old_custom . copy ( )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = old_custom . copy ( )
new_custom . update ( self . custom_firewall1 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' new ' : { ' Customizations.firewall ' : { ' ports ' : [ ' 22:tcp ' , ' 80:tcp ' , ' imap:tcp ' , ' 53:tcp ' , ' 53:udp ' ] ,
' services ' : { ' disabled ' : [ ' telnet ' ] , ' enabled ' : [ ' ftp ' , ' ntp ' , ' dhcp ' ] } } } ,
' old ' : None } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
# Test removing services
old_custom = self . old_custom . copy ( )
old_custom . update ( self . custom_firewall1 )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = self . old_custom . copy ( )
new_custom . update ( self . custom_firewall2 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' old ' : { ' Customizations.firewall ' : { ' ports ' : [ ' 22:tcp ' , ' 80:tcp ' , ' imap:tcp ' , ' 53:tcp ' , ' 53:udp ' ] ,
' services ' : { ' disabled ' : [ ' telnet ' ] , ' enabled ' : [ ' ftp ' , ' ntp ' , ' dhcp ' ] } } } ,
' new ' : { ' Customizations.firewall ' : { ' ports ' : [ ' 22:tcp ' , ' 80:tcp ' , ' imap:tcp ' , ' 53:tcp ' , ' 53:udp ' ] } } } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
# Test removing ports
old_custom = self . old_custom . copy ( )
old_custom . update ( self . custom_firewall1 )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = self . old_custom . copy ( )
new_custom . update ( self . custom_firewall3 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' old ' : { ' Customizations.firewall ' : { ' ports ' : [ ' 22:tcp ' , ' 80:tcp ' , ' imap:tcp ' , ' 53:tcp ' , ' 53:udp ' ] ,
' services ' : { ' disabled ' : [ ' telnet ' ] , ' enabled ' : [ ' ftp ' , ' ntp ' , ' dhcp ' ] } } } ,
' new ' : { ' Customizations.firewall ' : { ' services ' : { ' disabled ' : [ ' telnet ' ] , ' enabled ' : [ ' ftp ' , ' ntp ' , ' dhcp ' ] } } } } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
# Test removing disabled services
old_custom = self . old_custom . copy ( )
old_custom . update ( self . custom_firewall3 )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = self . old_custom . copy ( )
new_custom . update ( self . custom_firewall4 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' old ' : { ' Customizations.firewall ' : { ' services ' : { ' disabled ' : [ ' telnet ' ] , ' enabled ' : [ ' ftp ' , ' ntp ' , ' dhcp ' ] } } } ,
' new ' : { ' Customizations.firewall ' : { ' services ' : { ' enabled ' : [ ' ftp ' , ' ntp ' , ' dhcp ' ] } } } } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
# Test removing enabled services
old_custom = self . old_custom . copy ( )
old_custom . update ( self . custom_firewall3 )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = self . old_custom . copy ( )
new_custom . update ( self . custom_firewall5 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' old ' : { ' Customizations.firewall ' : { ' services ' : { ' disabled ' : [ ' telnet ' ] , ' enabled ' : [ ' ftp ' , ' ntp ' , ' dhcp ' ] } } } ,
' new ' : { ' Customizations.firewall ' : { ' services ' : { ' disabled ' : [ ' telnet ' ] } } } } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
def customizations_diff_locale_test ( self ) :
""" Test the customizations_diff function with locale variations """
# Test adding the locale customization
old_custom = self . old_custom . copy ( )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = old_custom . copy ( )
new_custom . update ( self . custom_locale1 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' new ' : { ' Customizations.locale ' : { ' keyboard ' : ' us ' , ' languages ' : [ ' en_US.UTF-8 ' ] } } ,
' old ' : None } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
# Test removing keyboard
old_custom = self . old_custom . copy ( )
old_custom . update ( self . custom_locale1 )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = self . old_custom . copy ( )
new_custom . update ( self . custom_locale2 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' old ' : { ' Customizations.locale ' : { ' keyboard ' : ' us ' , ' languages ' : [ ' en_US.UTF-8 ' ] } } ,
' new ' : { ' Customizations.locale ' : { ' languages ' : [ ' en_US.UTF-8 ' ] } } } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
# Test removing languages
old_custom = self . old_custom . copy ( )
old_custom . update ( self . custom_locale1 )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = self . old_custom . copy ( )
new_custom . update ( self . custom_locale3 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' old ' : { ' Customizations.locale ' : { ' keyboard ' : ' us ' , ' languages ' : [ ' en_US.UTF-8 ' ] } } ,
' new ' : { ' Customizations.locale ' : { ' keyboard ' : ' us ' } } } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
def customizations_diff_timezone_test ( self ) :
""" Test the customizations_diff function with timezone variations """
# Test adding the timezone customization
old_custom = self . old_custom . copy ( )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = old_custom . copy ( )
new_custom . update ( self . custom_timezone1 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' new ' : { ' Customizations.timezone ' : { ' ntpservers ' : [ ' 0.north-america.pool.ntp.org ' , ' 1.north-america.pool.ntp.org ' ] , ' timezone ' : ' US/Eastern ' } } ,
' old ' : None } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
# Test removing ntpservers
old_custom = self . old_custom . copy ( )
old_custom . update ( self . custom_timezone1 )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = self . old_custom . copy ( )
new_custom . update ( self . custom_timezone2 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' old ' : { ' Customizations.timezone ' : { ' ntpservers ' : [ ' 0.north-america.pool.ntp.org ' , ' 1.north-america.pool.ntp.org ' ] , ' timezone ' : ' US/Eastern ' } } ,
' new ' : { ' Customizations.timezone ' : { ' timezone ' : ' US/Eastern ' } } } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
# Test removing timezone
old_custom = self . old_custom . copy ( )
old_custom . update ( self . custom_timezone1 )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = self . old_custom . copy ( )
new_custom . update ( self . custom_timezone3 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' old ' : { ' Customizations.timezone ' : { ' ntpservers ' : [ ' 0.north-america.pool.ntp.org ' , ' 1.north-america.pool.ntp.org ' ] , ' timezone ' : ' US/Eastern ' } } ,
' new ' : { ' Customizations.timezone ' : { ' ntpservers ' : [ ' 0.north-america.pool.ntp.org ' , ' 1.north-america.pool.ntp.org ' ] } } } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
def customizations_diff_sshkey_test ( self ) :
""" Test the customizations_diff function with sshkey variations """
# Test changed root ssh key
old_custom = self . old_custom . copy ( )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = old_custom . copy ( )
new_custom . update ( self . custom_sshkey2 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' new ' : { ' Customizations.sshkey ' : { ' key ' : ' A DIFFERENT SSH KEY FOR ROOT ' , ' user ' : ' root ' } } ,
' old ' : { ' Customizations.sshkey ' : { ' key ' : ' A SSH KEY FOR ROOT ' , ' user ' : ' root ' } } } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
# Test adding a user's ssh key
old_custom = self . old_custom . copy ( )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = old_custom . copy ( )
new_custom . update ( self . custom_sshkey3 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' new ' : { ' Customizations.sshkey ' : { ' key ' : ' A SSH KEY FOR CLIFF ' , ' user ' : ' cliff ' } } ,
' old ' : None } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
# Test removing a user's ssh key
old_custom = old_custom . copy ( )
old_custom . update ( self . custom_sshkey3 )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = self . old_custom . copy ( )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' old ' : { ' Customizations.sshkey ' : { ' key ' : ' A SSH KEY FOR CLIFF ' , ' user ' : ' cliff ' } } ,
' new ' : None } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
def customizations_diff_user_test ( self ) :
""" Test the customizations_diff function with user variations """
# Test changed admin user
old_custom = self . old_custom . copy ( )
old_custom . update ( self . custom_user1 )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = old_custom . copy ( )
new_custom . update ( self . custom_user2 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' new ' : { ' Customizations.user ' : { ' description ' : ' Administrator account ' ,
' gid ' : 1200 ,
' groups ' : [ ' widget ' , ' users ' , ' wheel ' ] ,
' home ' : ' /root/ ' ,
' key ' : ' PUBLIC SSH KEY ' ,
' name ' : ' admin ' ,
' password ' : ' $6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31L... ' ,
' shell ' : ' /usr/bin/bash ' ,
' uid ' : 1200 } } ,
' old ' : { ' Customizations.user ' : { ' description ' : ' Administrator account ' ,
' gid ' : 1200 ,
' groups ' : [ ' widget ' , ' users ' , ' wheel ' ] ,
' home ' : ' /srv/widget/ ' ,
' key ' : ' PUBLIC SSH KEY ' ,
' name ' : ' admin ' ,
' password ' : ' $6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31L... ' ,
' shell ' : ' /usr/bin/bash ' ,
' uid ' : 1200 } } } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
# Test adding a user
old_custom = self . old_custom . copy ( )
old_custom . update ( self . custom_user1 )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = old_custom . copy ( )
new_custom . update ( self . custom_user3 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' new ' : { ' Customizations.user ' : { ' key ' : ' PUBLIC SSH KEY ' , ' name ' : ' norman ' } } , ' old ' : None } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
# Test removing a user
old_custom = self . old_custom . copy ( )
old_custom . update ( self . custom_user3 )
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , [ ] , [ ] , customizations = old_custom )
new_custom = old_custom . copy ( )
new_custom . update ( self . custom_user1 )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , [ ] , [ ] , [ ] , customizations = new_custom )
result = [ { ' new ' : None , ' old ' : { ' Customizations.user ' : { ' key ' : ' PUBLIC SSH KEY ' , ' name ' : ' norman ' } } } ]
self . assertEqual ( recipes . customizations_diff ( old_recipe , new_recipe ) , result )
2018-04-30 18:34:48 +00:00
def recipe_diff_test ( self ) :
""" Test the recipe_diff function """
2019-05-29 23:49:34 +00:00
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , self . old_modules , self . old_packages , [ ] )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , self . new_modules , self . new_packages , [ ] )
2019-05-14 18:44:18 +00:00
result = [ { ' new ' : { ' Version ' : ' 0.3.1 ' } , ' old ' : { ' Version ' : ' 0.1.1 ' } } ,
{ ' new ' : { ' Module ' : { ' name ' : ' openssh ' , ' version ' : ' 2.8.1 ' } } , ' old ' : None } ,
2019-05-29 23:49:34 +00:00
{ ' new ' : None , ' old ' : { ' Module ' : { ' name ' : ' bash ' , ' version ' : ' 4.* ' } } } ,
2019-05-14 18:44:18 +00:00
{ ' new ' : { ' Module ' : { ' name ' : ' httpd ' , ' version ' : ' 3.8.* ' } } ,
' old ' : { ' Module ' : { ' name ' : ' httpd ' , ' version ' : ' 3.7.* ' } } } ,
2019-05-29 23:49:34 +00:00
{ ' new ' : { ' Package ' : { ' name ' : ' git ' , ' version ' : ' 2.13.* ' } } , ' old ' : None } ]
2019-05-14 18:44:18 +00:00
self . assertEqual ( recipes . recipe_diff ( old_recipe , new_recipe ) , result )
# Empty starting recipe
2019-05-29 23:49:34 +00:00
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , [ ] , self . old_packages , [ ] )
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , self . new_modules , self . new_packages , [ ] )
2019-05-14 18:44:18 +00:00
result = [ { ' new ' : { ' Version ' : ' 0.3.1 ' } , ' old ' : { ' Version ' : ' 0.1.1 ' } } ,
{ ' new ' : { ' Module ' : { ' name ' : ' httpd ' , ' version ' : ' 3.8.* ' } } , ' old ' : None } ,
{ ' new ' : { ' Module ' : { ' name ' : ' openssh ' , ' version ' : ' 2.8.1 ' } } , ' old ' : None } ,
{ ' new ' : { ' Module ' : { ' name ' : ' toml ' , ' version ' : ' 2.1 ' } } , ' old ' : None } ,
2019-05-29 23:49:34 +00:00
{ ' new ' : { ' Package ' : { ' name ' : ' git ' , ' version ' : ' 2.13.* ' } } , ' old ' : None } ]
2019-05-14 18:44:18 +00:00
self . assertEqual ( recipes . recipe_diff ( old_recipe , new_recipe ) , result )
# All new git repos
2018-07-10 20:59:41 +00:00
old_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.1.1 " , self . old_modules , self . old_packages , [ ] )
2019-05-29 23:49:34 +00:00
new_recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , " 0.3.1 " , self . new_modules , self . new_packages , [ ] )
2018-04-30 18:34:48 +00:00
result = [ { ' new ' : { ' Version ' : ' 0.3.1 ' } , ' old ' : { ' Version ' : ' 0.1.1 ' } } ,
{ ' new ' : { ' Module ' : { ' name ' : ' openssh ' , ' version ' : ' 2.8.1 ' } } , ' old ' : None } ,
{ ' new ' : None , ' old ' : { ' Module ' : { ' name ' : ' bash ' , ' version ' : ' 4.* ' } } } ,
{ ' new ' : { ' Module ' : { ' name ' : ' httpd ' , ' version ' : ' 3.8.* ' } } ,
' old ' : { ' Module ' : { ' name ' : ' httpd ' , ' version ' : ' 3.7.* ' } } } ,
2019-05-29 23:49:34 +00:00
{ ' new ' : { ' Package ' : { ' name ' : ' git ' , ' version ' : ' 2.13.* ' } } , ' old ' : None } ]
2018-04-30 18:34:48 +00:00
self . assertEqual ( recipes . recipe_diff ( old_recipe , new_recipe ) , result )
2019-02-07 17:48:17 +00:00
def recipe_freeze_test ( self ) :
""" Test the recipe freeze() function """
# Use the repos-git.toml test, it only has http and php in it
deps = [ { " arch " : " x86_64 " ,
" epoch " : 0 ,
" name " : " httpd " ,
" release " : " 1.el7 " ,
" version " : " 2.4.11 " } ,
{ " arch " : " x86_64 " ,
" epoch " : 0 ,
" name " : " php " ,
" release " : " 1.el7 " ,
" version " : " 5.4.2 " } ]
result = recipes . recipe_from_toml ( self . input_toml [ " repos-git.toml " ] [ 0 ] )
self . assertEqual ( result , self . input_toml [ " repos-git.toml " ] [ 1 ] )
# Freeze the recipe with our fake deps
frozen = result . freeze ( deps )
self . assertTrue ( frozen is not None )
http_module = recipes . find_name ( " httpd " , frozen [ " modules " ] )
self . assertTrue ( http_module is not None )
self . assertEqual ( http_module [ " version " ] , " 2.4.11-1.el7.x86_64 " )
php_module = recipes . find_name ( " php " , frozen [ " modules " ] )
self . assertTrue ( php_module is not None )
self . assertEqual ( php_module [ " version " ] , " 5.4.2-1.el7.x86_64 " )
2018-04-30 18:34:48 +00:00
class GitRecipesTest ( unittest . TestCase ) :
@classmethod
def setUpClass ( self ) :
self . repo_dir = tempfile . mkdtemp ( prefix = " lorax.test.repo. " )
self . repo = recipes . open_or_create_repo ( self . repo_dir )
self . results_path = " ./tests/pylorax/results/ "
self . examples_path = " ./tests/pylorax/blueprints/ "
self . new_recipe = os . path . join ( self . examples_path , ' python-testing.toml ' )
@classmethod
def tearDownClass ( self ) :
if self . repo is not None :
del self . repo
shutil . rmtree ( self . repo_dir )
def tearDown ( self ) :
if os . path . exists ( self . new_recipe ) :
os . remove ( self . new_recipe )
def _create_another_recipe ( self ) :
open ( self . new_recipe , ' w ' ) . write ( """ name = " python-testing "
description = " A recipe used during testing. "
version = " 0.0.1 "
[ [ packages ] ]
name = " python "
version = " 2.7.* "
""" )
def test_01_repo_creation ( self ) :
""" Test that creating the repository succeeded """
self . assertNotEqual ( self . repo , None )
def test_02_commit_recipe ( self ) :
""" Test committing a Recipe object """
2018-07-10 20:59:41 +00:00
recipe = recipes . Recipe ( " test-recipe " , " A recipe used for testing " , None , None , None , None )
2018-04-30 18:34:48 +00:00
oid = recipes . commit_recipe ( self . repo , " master " , recipe )
self . assertNotEqual ( oid , None )
def test_03_list_recipe ( self ) :
""" Test listing recipe commits """
commits = recipes . list_commits ( self . repo , " master " , " test-recipe.toml " )
self . assertEqual ( len ( commits ) , 1 , " Wrong number of commits. " )
self . assertEqual ( commits [ 0 ] . message , " Recipe test-recipe, version 0.0.1 saved. " )
self . assertNotEqual ( commits [ 0 ] . timestamp , None , " Timestamp is None " )
self . assertEqual ( len ( commits [ 0 ] . commit ) , 40 , " Commit hash isn ' t 40 characters " )
self . assertEqual ( commits [ 0 ] . revision , None , " revision is not None " )
def test_03_list_commits_commit_time_val_error ( self ) :
""" Test listing recipe commits which raise CommitTimeValError """
with mock . patch ( ' pylorax.api.recipes.GLib.DateTime.to_timeval ' , return_value = False ) :
commits = recipes . list_commits ( self . repo , " master " , " test-recipe.toml " )
self . assertEqual ( len ( commits ) , 0 , " Wrong number of commits. " )
def test_04_commit_recipe_file ( self ) :
""" Test committing a TOML file """
recipe_path = joinpaths ( self . results_path , " full-recipe.toml " )
oid = recipes . commit_recipe_file ( self . repo , " master " , recipe_path )
self . assertNotEqual ( oid , None )
commits = recipes . list_commits ( self . repo , " master " , " http-server.toml " )
self . assertEqual ( len ( commits ) , 1 , " Wrong number of commits: %s " % commits )
def test_04_commit_recipe_file_handles_internal_ioerror ( self ) :
""" Test committing a TOML raises RecipeFileError on internal IOError """
recipe_path = joinpaths ( self . results_path , " non-existing-file.toml " )
with self . assertRaises ( recipes . RecipeFileError ) :
recipes . commit_recipe_file ( self . repo , " master " , recipe_path )
def test_05_commit_toml_dir ( self ) :
""" Test committing a directory of TOML files """
# first verify that the newly created file isn't present
old_commits = recipes . list_commits ( self . repo , " master " , " python-testing.toml " )
self . assertEqual ( len ( old_commits ) , 0 , " Wrong number of commits: %s " % old_commits )
# then create it and commit the entire directory
self . _create_another_recipe ( )
recipes . commit_recipe_directory ( self . repo , " master " , self . examples_path )
# verify that the newly created file is already in the repository
new_commits = recipes . list_commits ( self . repo , " master " , " python-testing.toml " )
self . assertEqual ( len ( new_commits ) , 1 , " Wrong number of commits: %s " % new_commits )
# again make sure new_commits != old_commits
self . assertGreater ( len ( new_commits ) , len ( old_commits ) ,
" New commits shoud differ from old commits " )
def test_05_commit_recipe_directory_handling_internal_exceptions ( self ) :
""" Test committing a directory of TOML files while handling internal exceptions """
# first verify that the newly created file isn't present
old_commits = recipes . list_commits ( self . repo , " master " , " python-testing.toml " )
self . assertEqual ( len ( old_commits ) , 0 , " Wrong number of commits: %s " % old_commits )
# then create it and commit the entire directory
self . _create_another_recipe ( )
# try to commit while raising RecipeFileError
with mock . patch ( ' pylorax.api.recipes.commit_recipe_file ' , side_effect = recipes . RecipeFileError ( ' TESTING ' ) ) :
recipes . commit_recipe_directory ( self . repo , " master " , self . examples_path )
# try to commit while raising TomlError
with mock . patch ( ' pylorax.api.recipes.commit_recipe_file ' , side_effect = TomlError ( ' TESTING ' , 0 , 0 , ' __test__ ' ) ) :
recipes . commit_recipe_directory ( self . repo , " master " , self . examples_path )
# verify again that the newly created file isn't present b/c we raised an exception
new_commits = recipes . list_commits ( self . repo , " master " , " python-testing.toml " )
self . assertEqual ( len ( new_commits ) , 0 , " Wrong number of commits: %s " % new_commits )
def test_06_read_recipe ( self ) :
""" Test reading a recipe from a commit """
2018-08-21 22:08:58 +00:00
commits = recipes . list_commits ( self . repo , " master " , " example-http-server.toml " )
2018-04-30 18:34:48 +00:00
self . assertEqual ( len ( commits ) , 1 , " Wrong number of commits: %s " % commits )
2018-08-21 22:08:58 +00:00
recipe = recipes . read_recipe_commit ( self . repo , " master " , " example-http-server " )
2018-04-30 18:34:48 +00:00
self . assertNotEqual ( recipe , None )
2018-08-21 22:08:58 +00:00
self . assertEqual ( recipe [ " name " ] , " example-http-server " )
2018-04-30 18:34:48 +00:00
# Read by commit id
2018-08-21 22:08:58 +00:00
recipe = recipes . read_recipe_commit ( self . repo , " master " , " example-http-server " , commits [ 0 ] . commit )
2018-04-30 18:34:48 +00:00
self . assertNotEqual ( recipe , None )
2018-08-21 22:08:58 +00:00
self . assertEqual ( recipe [ " name " ] , " example-http-server " )
2018-04-30 18:34:48 +00:00
# Read the recipe and its commit id
2018-08-21 22:08:58 +00:00
( commit_id , recipe ) = recipes . read_recipe_and_id ( self . repo , " master " , " example-http-server " , commits [ 0 ] . commit )
2018-04-30 18:34:48 +00:00
self . assertEqual ( commit_id , commits [ 0 ] . commit )
def test_07_tag_commit ( self ) :
""" Test tagging the most recent commit of a recipe """
result = recipes . tag_file_commit ( self . repo , " master " , " not-a-file " )
self . assertEqual ( result , None )
2018-08-21 22:08:58 +00:00
result = recipes . tag_recipe_commit ( self . repo , " master " , " example-http-server " )
2018-04-30 18:34:48 +00:00
self . assertNotEqual ( result , None )
2018-08-21 22:08:58 +00:00
commits = recipes . list_commits ( self . repo , " master " , " example-http-server.toml " )
2018-04-30 18:34:48 +00:00
self . assertEqual ( len ( commits ) , 1 , " Wrong number of commits: %s " % commits )
self . assertEqual ( commits [ 0 ] . revision , 1 )
def test_08_delete_recipe ( self ) :
""" Test deleting a file from a branch """
2018-08-21 22:08:58 +00:00
oid = recipes . delete_recipe ( self . repo , " master " , " example-http-server " )
2018-04-30 18:34:48 +00:00
self . assertNotEqual ( oid , None )
master_files = recipes . list_branch_files ( self . repo , " master " )
2018-08-21 22:08:58 +00:00
self . assertEqual ( " example-http-server.toml " in master_files , False )
2018-04-30 18:34:48 +00:00
def test_09_revert_commit ( self ) :
""" Test reverting a file on a branch """
2018-08-21 22:08:58 +00:00
commits = recipes . list_commits ( self . repo , " master " , " example-http-server.toml " )
2018-04-30 18:34:48 +00:00
revert_to = commits [ 0 ] . commit
2018-08-21 22:08:58 +00:00
oid = recipes . revert_recipe ( self . repo , " master " , " example-http-server " , revert_to )
2018-04-30 18:34:48 +00:00
self . assertNotEqual ( oid , None )
2018-08-21 22:08:58 +00:00
commits = recipes . list_commits ( self . repo , " master " , " example-http-server.toml " )
2018-04-30 18:34:48 +00:00
self . assertEqual ( len ( commits ) , 2 , " Wrong number of commits: %s " % commits )
2018-08-21 22:08:58 +00:00
self . assertEqual ( commits [ 0 ] . message , " example-http-server.toml reverted to commit %s " % revert_to )
2018-04-30 18:34:48 +00:00
def test_10_tag_new_commit ( self ) :
""" Test tagging a newer commit of a recipe """
2018-08-21 22:08:58 +00:00
recipe = recipes . read_recipe_commit ( self . repo , " master " , " example-http-server " )
2018-04-30 18:34:48 +00:00
recipe [ " description " ] = " A modified description "
oid = recipes . commit_recipe ( self . repo , " master " , recipe )
self . assertNotEqual ( oid , None )
# Tag the new commit
2018-08-21 22:08:58 +00:00
result = recipes . tag_recipe_commit ( self . repo , " master " , " example-http-server " )
2018-04-30 18:34:48 +00:00
self . assertNotEqual ( result , None )
2018-08-21 22:08:58 +00:00
commits = recipes . list_commits ( self . repo , " master " , " example-http-server.toml " )
2018-04-30 18:34:48 +00:00
self . assertEqual ( len ( commits ) , 3 , " Wrong number of commits: %s " % commits )
self . assertEqual ( commits [ 0 ] . revision , 2 )
class ExistingGitRepoRecipesTest ( GitRecipesTest ) :
@classmethod
def setUpClass ( self ) :
# will initialize the git repository in the parent class
super ( ExistingGitRepoRecipesTest , self ) . setUpClass ( )
# reopen the repository again so that tests are executed
# against the existing repo one more time.
self . repo = recipes . open_or_create_repo ( self . repo_dir )
class GetRevisionFromTagTests ( unittest . TestCase ) :
def test_01_valid_tag ( self ) :
revision = recipes . get_revision_from_tag ( ' branch/filename/r123 ' )
self . assertEqual ( 123 , revision )
def test_02_invalid_tag_not_a_number ( self ) :
revision = recipes . get_revision_from_tag ( ' branch/filename/rABC ' )
self . assertIsNone ( revision )
def test_02_invalid_tag_missing_revision_string ( self ) :
revision = recipes . get_revision_from_tag ( ' branch/filename/mybranch ' )
self . assertIsNone ( revision )
2018-12-21 17:51:52 +00:00
class CustomizationsTests ( unittest . TestCase ) :
@staticmethod
def _blueprint_to_ks ( blueprint_data ) :
recipe_obj = recipes . recipe_from_toml ( blueprint_data )
ks = KickstartParser ( makeVersion ( ) )
# write out the customization data, and parse the resulting kickstart
with tempfile . NamedTemporaryFile ( prefix = " lorax.test.customizations " , mode = " w " ) as f :
2019-04-09 23:37:24 +00:00
f . write ( customize_ks_template ( " " , recipe_obj ) )
2018-12-21 17:51:52 +00:00
add_customizations ( f , recipe_obj )
f . flush ( )
ks . readKickstart ( f . name )
return ks
@staticmethod
def _find_user ( ks , username ) :
for user in ks . handler . user . userList :
if user . name == username :
return user
2019-01-08 19:38:26 +00:00
return None
2018-12-21 17:51:52 +00:00
@staticmethod
def _find_sshkey ( ks , username ) :
for key in ks . handler . sshkey . sshUserList :
if key . username == username :
return key
2019-01-08 19:38:26 +00:00
return None
2018-12-21 17:51:52 +00:00
@staticmethod
def _find_group ( ks , groupname ) :
for group in ks . handler . group . groupList :
if group . name == groupname :
return group
2019-01-08 19:38:26 +00:00
return None
2018-12-21 17:51:52 +00:00
def test_hostname ( self ) :
blueprint_data = """ name = " test-hostname "
description = " test recipe "
version = " 0.0.1 "
[ customizations ]
hostname = " testy.example.com "
"""
ks = self . _blueprint_to_ks ( blueprint_data )
self . assertEqual ( ks . handler . network . hostname , " testy.example.com " )
def test_hostname_list ( self ) :
""" Test that the hostname still works when using [[customizations]] instead of [customizations] """
blueprint_data = """ name = " test-hostname-list "
description = " test recipe "
version = " 0.0.1 "
[ [ customizations ] ]
hostname = " testy.example.com "
"""
ks = self . _blueprint_to_ks ( blueprint_data )
self . assertEqual ( ks . handler . network . hostname , " testy.example.com " )
2019-04-09 23:37:24 +00:00
def test_timezone ( self ) :
blueprint_data = """ name = " test-timezone "
description = " test recipe "
version = " 0.0.1 "
[ customizations . timezone ]
timezone = " US/Samoa "
"""
ks = self . _blueprint_to_ks ( blueprint_data )
self . assertEqual ( ks . handler . timezone . timezone , " US/Samoa " )
def test_timezone_ntpservers ( self ) :
blueprint_data = """ name = " test-ntpservers "
description = " test recipe "
version = " 0.0.1 "
[ customizations . timezone ]
timezone = " US/Samoa "
ntpservers = [ " 1.north-america.pool.ntp.org " ]
"""
ks = self . _blueprint_to_ks ( blueprint_data )
self . assertEqual ( ks . handler . timezone . timezone , " US/Samoa " )
self . assertEqual ( ks . handler . timezone . ntpservers , [ " 1.north-america.pool.ntp.org " ] )
2019-04-12 19:23:20 +00:00
def test_locale_languages ( self ) :
blueprint_data = """ name = " test-locale "
description = " test recipe "
version = " 0.0.1 "
"""
blueprint2_data = blueprint_data + """
[ customizations . locale ]
languages = [ " en_CA.utf8 " ]
"""
blueprint3_data = blueprint_data + """
[ customizations . locale ]
languages = [ " en_CA.utf8 " , " en_HK.utf8 " ]
"""
ks = self . _blueprint_to_ks ( blueprint2_data )
self . assertEqual ( ks . handler . lang . lang , " en_CA.utf8 " )
self . assertEqual ( ks . handler . lang . addsupport , [ ] )
ks = self . _blueprint_to_ks ( blueprint3_data )
self . assertEqual ( ks . handler . lang . lang , " en_CA.utf8 " )
self . assertEqual ( ks . handler . lang . addsupport , [ " en_HK.utf8 " ] )
def test_locale_keyboard ( self ) :
blueprint_data = """ name = " test-locale "
description = " test recipe "
version = " 0.0.1 "
"""
blueprint2_data = blueprint_data + """
[ customizations . locale ]
keyboard = " us "
"""
blueprint3_data = blueprint_data + """
[ customizations . locale ]
keyboard = " de (dvorak) "
"""
ks = self . _blueprint_to_ks ( blueprint2_data )
self . assertEqual ( ks . handler . keyboard . keyboard , " us " )
ks = self . _blueprint_to_ks ( blueprint3_data )
self . assertEqual ( ks . handler . keyboard . keyboard , " de (dvorak) " )
def test_locale ( self ) :
blueprint_data = """ name = " test-locale "
description = " test recipe "
version = " 0.0.1 "
[ customizations . locale ]
keyboard = " de (dvorak) "
languages = [ " en_CA.utf8 " , " en_HK.utf8 " ]
"""
ks = self . _blueprint_to_ks ( blueprint_data )
self . assertEqual ( ks . handler . keyboard . keyboard , " de (dvorak) " )
self . assertEqual ( ks . handler . lang . lang , " en_CA.utf8 " )
self . assertEqual ( ks . handler . lang . addsupport , [ " en_HK.utf8 " ] )
2019-04-15 18:55:51 +00:00
def test_firewall_ports ( self ) :
blueprint_data = """ name = " test-firewall "
description = " test recipe "
version = " 0.0.1 "
"""
blueprint2_data = blueprint_data + """
[ customizations . firewall ]
ports = [ " 22:tcp " , " 80:tcp " , " imap:tcp " , " 53:tcp " , " 53:udp " ]
"""
ks = self . _blueprint_to_ks ( blueprint_data )
self . assertEqual ( ks . handler . firewall . ports , [ ] )
self . assertEqual ( ks . handler . firewall . services , [ ] )
self . assertEqual ( ks . handler . firewall . remove_services , [ ] )
ks = self . _blueprint_to_ks ( blueprint2_data )
2019-04-17 18:08:16 +00:00
self . assertEqual ( ks . handler . firewall . ports , [ " 22:tcp " , " 53:tcp " , " 53:udp " , " 80:tcp " , " imap:tcp " ] )
2019-04-15 18:55:51 +00:00
self . assertEqual ( ks . handler . firewall . services , [ ] )
self . assertEqual ( ks . handler . firewall . remove_services , [ ] )
def test_firewall_services ( self ) :
blueprint_data = """ name = " test-firewall "
description = " test recipe "
version = " 0.0.1 "
[ customizations . firewall . services ]
enabled = [ " ftp " , " ntp " , " dhcp " ]
disabled = [ " telnet " ]
"""
ks = self . _blueprint_to_ks ( blueprint_data )
self . assertEqual ( ks . handler . firewall . ports , [ ] )
2019-04-17 18:08:16 +00:00
self . assertEqual ( ks . handler . firewall . services , [ " dhcp " , " ftp " , " ntp " ] )
2019-04-15 18:55:51 +00:00
self . assertEqual ( ks . handler . firewall . remove_services , [ " telnet " ] )
def test_firewall ( self ) :
blueprint_data = """ name = " test-firewall "
description = " test recipe "
version = " 0.0.1 "
[ customizations . firewall ]
ports = [ " 22:tcp " , " 80:tcp " , " imap:tcp " , " 53:tcp " , " 53:udp " ]
[ customizations . firewall . services ]
enabled = [ " ftp " , " ntp " , " dhcp " ]
disabled = [ " telnet " ]
"""
ks = self . _blueprint_to_ks ( blueprint_data )
2019-04-17 18:08:16 +00:00
self . assertEqual ( ks . handler . firewall . ports , [ " 22:tcp " , " 53:tcp " , " 53:udp " , " 80:tcp " , " imap:tcp " ] )
self . assertEqual ( ks . handler . firewall . services , [ " dhcp " , " ftp " , " ntp " ] )
2019-04-15 18:55:51 +00:00
self . assertEqual ( ks . handler . firewall . remove_services , [ " telnet " ] )
2019-04-16 23:40:40 +00:00
def test_services ( self ) :
blueprint_data = """ name = " test-services "
description = " test recipe "
version = " 0.0.1 "
[ customizations . services ]
enabled = [ " sshd " , " cockpit.socket " , " httpd " ]
disabled = [ " postfix " , " telnetd " ]
"""
ks = self . _blueprint_to_ks ( blueprint_data )
self . assertEqual ( sorted ( ks . handler . services . enabled ) , [ " cockpit.socket " , " httpd " , " sshd " ] )
self . assertEqual ( sorted ( ks . handler . services . disabled ) , [ " postfix " , " telnetd " ] )
2018-12-21 17:51:52 +00:00
def test_user ( self ) :
blueprint_data = """ name = " test-user "
description = " test recipe "
version = " 0.0.1 "
[ [ customizations . user ] ]
name = " admin "
description = " Widget admin account "
password = " $6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31LeOUleVK/R/aeWVHVZDi26zAH.o0ywBKH9Tc0/wm7sW/q39uyd1 "
home = " /srv/widget/ "
shell = " /usr/bin/bash "
groups = [ " widget " , " users " , " students " ]
uid = 1200
[ [ customizations . user ] ]
name = " bart "
key = " SSH KEY FOR BART "
groups = [ " students " ]
"""
ks = self . _blueprint_to_ks ( blueprint_data )
admin = self . _find_user ( ks , " admin " )
self . assertIsNotNone ( admin )
self . assertEqual ( admin . name , " admin " )
self . assertEqual ( admin . password , " $6$CHO2$3rN8eviE2t50lmVyBYihTgVRHcaecmeCk31LeOUleVK/R/aeWVHVZDi26zAH.o0ywBKH9Tc0/wm7sW/q39uyd1 " )
self . assertEqual ( admin . homedir , " /srv/widget/ " )
self . assertEqual ( admin . shell , " /usr/bin/bash " )
# order is unimportant, so use a set instead of comparing lists directly
self . assertEqual ( set ( admin . groups ) , { " widget " , " users " , " students " } )
self . assertEqual ( admin . uid , 1200 )
bart = self . _find_user ( ks , " bart " )
self . assertIsNotNone ( bart )
self . assertEqual ( bart . name , " bart " )
self . assertEqual ( bart . groups , [ " students " ] )
bartkey = self . _find_sshkey ( ks , " bart " )
self . assertIsNotNone ( bartkey )
self . assertEqual ( bartkey . username , " bart " )
self . assertEqual ( bartkey . key , " SSH KEY FOR BART " )
def test_group ( self ) :
blueprint_data = """ name = " test-group "
description = " test recipe "
version = " 0.0.1 "
[ [ customizations . group ] ]
name = " widget "
[ [ customizations . group ] ]
name = " students "
"""
ks = self . _blueprint_to_ks ( blueprint_data )
widget = self . _find_group ( ks , " widget " )
self . assertIsNotNone ( widget )
students = self . _find_group ( ks , " students " )
self . assertIsNotNone ( students )
def test_full ( self ) :
blueprint_data = """ name = " custom-base "
description = " A base system with customizations "
version = " 0.0.1 "
modules = [ ]
groups = [ ]
[ [ packages ] ]
name = " bash "
version = " 4.4.* "
[ [ customizations ] ]
hostname = " custom-base "
[ [ customizations . sshkey ] ]
user = " root "
key = " ssh-rsa "
[ [ customizations . user ] ]
name = " widget "
description = " Widget process user account "
home = " /srv/widget/ "
shell = " /usr/bin/false "
groups = [ " dialout " , " users " ]
[ [ customizations . user ] ]
name = " admin "
description = " Widget admin account "
password = " "
home = " /srv/widget/ "
shell = " /usr/bin/bash "
groups = [ " widget " , " users " , " students " ]
uid = 1200
[ [ customizations . user ] ]
name = " plain "
password = " password "
[ [ customizations . user ] ]
name = " bart "
key = " "
groups = [ " students " ]
[ [ customizations . group ] ]
name = " widget "
[ [ customizations . group ] ]
name = " students "
2019-04-09 23:37:24 +00:00
[ customizations . timezone ]
timezone = " US/Samoa "
ntpservers = [ " 0.north-america.pool.ntp.org " , " 1.north-america.pool.ntp.org " ]
2018-12-21 17:51:52 +00:00
"""
ks = self . _blueprint_to_ks ( blueprint_data )
self . assertEqual ( ks . handler . network . hostname , " custom-base " )
rootkey = self . _find_sshkey ( ks , " root " )
self . assertIsNotNone ( rootkey )
self . assertEqual ( rootkey . username , " root " )
self . assertEqual ( rootkey . key , " ssh-rsa " )
widget = self . _find_user ( ks , " widget " )
self . assertIsNotNone ( widget )
self . assertEqual ( widget . name , " widget " )
self . assertEqual ( widget . homedir , " /srv/widget/ " )
self . assertEqual ( widget . shell , " /usr/bin/false " )
self . assertEqual ( set ( widget . groups ) , { " dialout " , " users " } )
admin = self . _find_user ( ks , " admin " )
self . assertIsNotNone ( admin )
self . assertEqual ( admin . name , " admin " )
self . assertEqual ( admin . password , " " )
self . assertEqual ( admin . homedir , " /srv/widget/ " )
self . assertEqual ( admin . shell , " /usr/bin/bash " )
self . assertEqual ( set ( admin . groups ) , { " widget " , " users " , " students " } )
self . assertEqual ( admin . uid , 1200 )
plain = self . _find_user ( ks , " plain " )
self . assertIsNotNone ( plain )
self . assertEqual ( plain . name , " plain " )
self . assertEqual ( plain . password , " password " )
# widget does not appear as a separate group line, since a widget
# group is created for the widget user
widgetGroup = self . _find_group ( ks , " widget " )
self . assertIsNone ( widgetGroup )
studentsGroup = self . _find_group ( ks , " students " )
self . assertIsNotNone ( studentsGroup )
self . assertEqual ( studentsGroup . name , " students " )
2019-04-09 23:37:24 +00:00
self . assertEqual ( ks . handler . timezone . timezone , " US/Samoa " )
self . assertEqual ( ks . handler . timezone . ntpservers , [ " 0.north-america.pool.ntp.org " , " 1.north-america.pool.ntp.org " ] )
2019-06-21 23:46:19 +00:00
class RecipeDictTest ( unittest . TestCase ) :
def test_check_list_case ( self ) :
""" Test the list case checker function """
self . assertEqual ( recipes . check_list_case ( [ ] , [ ] ) , [ ] )
self . assertEqual ( recipes . check_list_case ( [ " name " , " description " , " version " ] , [ ] ) , [ ] )
self . assertEqual ( recipes . check_list_case ( [ " name " , " description " , " version " ] ,
[ " name " , " description " , " version " ] ) , [ ] )
self . assertEqual ( recipes . check_list_case ( [ " name " , " description " , " version " ] ,
[ " name " , " Description " , " VERSION " ] ) ,
[ " Description should be description " , " VERSION should be version " ] )
self . assertEqual ( recipes . check_list_case ( [ " append " ] , [ " appEnD " ] , prefix = " kernel " ) ,
[ " kernel appEnD should be append " ] )
def test_check_required_list ( self ) :
""" Test the required list function """
self . assertEqual ( recipes . check_required_list ( [ { } ] , [ " name " , " version " ] ) ,
[ " 1 is missing ' name ' , ' version ' " ] )
self . assertEqual ( recipes . check_required_list ( [ { " name " : " foo " , " version " : " 1.0.0 " } ] , [ " name " , " version " ] ) ,
[ ] )
self . assertEqual ( recipes . check_required_list ( [ { " Name " : " foo " , " Version " : " 1.0.0 " } ] , [ " name " , " version " ] ) ,
[ ' 1 Name should be name ' , ' 1 Version should be version ' , " 1 is missing ' name ' , ' version ' " ] )
def test_check_recipe_dict ( self ) :
""" Test the recipe dict checker function """
r = { }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " Missing ' name ' " , " Missing ' description ' " ] )
r [ " name " ] = " recipe name "
r [ " description " ] = " recipe description "
r [ " version " ] = " 92ee0ad691 "
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " Invalid ' version ' , must use Semantic Versioning " ] )
r [ " version " ] = " 0.0.1 "
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ] )
r [ " modules " ] = [ { " name " : " mod1 " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' modules ' errors: \n 1 is missing ' version ' " ] )
r [ " modules " ] = [ { " name " : " mod1 " , " version " : " * " } , { " Name " : " mod2 " , " Version " : " 1.0 " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' modules ' errors: \n 2 Name should be name \n 2 Version should be version \n 2 is missing ' name ' , ' version ' " ] )
r [ " modules " ] = [ { " name " : " mod1 " , " version " : " * " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ] )
r [ " packages " ] = [ { " name " : " pkg1 " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' packages ' errors: \n 1 is missing ' version ' " ] )
r [ " packages " ] = [ { " name " : " pkg1 " , " version " : " * " } , { " Name " : " pkg2 " , " Version " : " 1.0 " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' packages ' errors: \n 2 Name should be name \n 2 Version should be version \n 2 is missing ' name ' , ' version ' " ] )
r [ " packages " ] = [ { " name " : " pkg1 " , " version " : " * " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ] )
r [ " groups " ] = [ { } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' groups ' errors: \n 1 is missing ' name ' " ] )
r [ " groups " ] = [ { " Name " : " grp1 " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' groups ' errors: \n 1 Name should be name \n 1 is missing ' name ' " ] )
r [ " groups " ] = [ { " name " : " grp1 " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ] )
r [ " customizations " ] = { " kernel " : { } }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' customizations.kernel ' : missing append field. " ] )
r [ " customizations " ] = { " kernel " : { " Append " : " cmdline-arg " } }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ' kernel Append should be append ' , " ' customizations.kernel ' : missing append field. " ] )
r [ " customizations " ] = { " kernel " : { " append " : " cmdline-arg " } }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ] )
r [ " customizations " ] [ " sshkey " ] = [ { " key " : " KEY " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' customizations.sshkey ' errors: \n 1 is missing ' user ' " ] )
r [ " customizations " ] [ " sshkey " ] = [ { " user " : " username " , " KEY " : " KEY " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' customizations.sshkey ' errors: \n 1 KEY should be key \n 1 is missing ' key ' " ] )
r [ " customizations " ] [ " sshkey " ] = [ { " user " : " username " , " key " : " KEY " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ] )
r [ " customizations " ] [ " user " ] = [ { " password " : " FOOBAR " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' customizations.user ' errors: \n 1 is missing ' name ' " ] )
r [ " customizations " ] [ " user " ] = [ { " naMe " : " admin " , " key " : " KEY " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' customizations.user ' errors: \n 1 naMe should be name \n 1 is missing ' name ' " ] )
r [ " customizations " ] [ " user " ] = [ { " name " : " admin " , " key " : " KEY " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ] )
r [ " customizations " ] [ " group " ] = [ { " id " : " 2001 " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' customizations.group ' errors: \n 1 is missing ' name ' " ] )
r [ " customizations " ] [ " group " ] = [ { " Name " : " admins " , " id " : " 2001 " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' customizations.group ' errors: \n 1 Name should be name \n 1 is missing ' name ' " ] )
r [ " customizations " ] [ " group " ] = [ { " name " : " admins " , " id " : " 2001 " } ]
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ] )
r [ " customizations " ] [ " timezone " ] = { }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' customizations.timezone ' : missing timezone or ntpservers fields. " ] )
r [ " customizations " ] [ " timezone " ] = { " Timezone " : " PST8PDT " }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ' timezone Timezone should be timezone ' ] )
r [ " customizations " ] [ " timezone " ] = { " timezone " : " PST8PDT " }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ] )
r [ " customizations " ] [ " locale " ] = { }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' customizations.locale ' : missing languages or keyboard fields. " ] )
r [ " customizations " ] [ " locale " ] = { " Keyboard " : " dvorak " }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ' locale Keyboard should be keyboard ' ] )
r [ " customizations " ] [ " locale " ] = { " keyboard " : " dvorak " }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ] )
r [ " customizations " ] [ " firewall " ] = { }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' customizations.firewall ' : missing ports field or services section. " ] )
r [ " customizations " ] [ " firewall " ] = { " Ports " : " 8080:tcp " }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ' firewall Ports should be ports ' ] )
r [ " customizations " ] [ " firewall " ] = { " ports " : " 8080:tcp " }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ] )
r [ " customizations " ] [ " firewall " ] [ " services " ] = { }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' customizations.firewall.services ' : missing enabled or disabled fields. " ] )
r [ " customizations " ] [ " firewall " ] [ " services " ] = { " enabled " : " sshd " }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ] )
r [ " customizations " ] [ " services " ] = { }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ " ' customizations.services ' : missing enabled or disabled fields. " ] )
r [ " customizations " ] [ " services " ] = { " DISABLED " : " telnetd " }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ' services DISABLED should be disabled ' ] )
r [ " customizations " ] [ " services " ] = { " disabled " : " telnetd " }
self . assertEqual ( recipes . check_recipe_dict ( r ) , [ ] )