Skip to content

Commit

Permalink
Merge pull request #101 from mayn/mayn-issue91
Browse files Browse the repository at this point in the history
add jagged array validator to correct list of list error
  • Loading branch information
mayn authored Mar 18, 2018
2 parents a764e5a + 7877c95 commit 6d478b0
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 25 deletions.
20 changes: 10 additions & 10 deletions src/packerlicious/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ class AmazonChroot(PackerBuilder):
'ami_regions': ([str], False),
'ami_users': ([str], False),
'ami_virtualization_type': (str, False),
'chroot_mounts': ([[str]], False),
'chroot_mounts': (validator.jagged_array(str), False),
'command_wrapper': (str, False),
'copy_files': ([str], False),
'custom_endpoint_ec2': (str, False),
Expand Down Expand Up @@ -1034,8 +1034,8 @@ class ParallelsIso(PackerBuilder):
'output_directory': (str, False),
'parallels_tools_guest_path': (str, False),
'parallels_tools_mode': (str, False),
'prlctl': ([[str]], False),
'prlctl_post': ([[str]], False),
'prlctl': (validator.jagged_array(str), False),
'prlctl_post': (validator.jagged_array(str), False),
'prlctl_version_file': (str, False),
'shutdown_command': (str, False),
'shutdown_timeout': (str, False),
Expand Down Expand Up @@ -1068,8 +1068,8 @@ class ParallelsPvm(PackerBuilder):
'output_directory': (str, False),
'parallels_tools_guest_path': (str, False),
'parallels_tools_mode': (str, False),
'prlctl': ([[str]], False),
'prlctl_post': ([[str]], False),
'prlctl': (validator.jagged_array(str), False),
'prlctl_post': (validator.jagged_array(str), False),
'prlctl_version_file': (str, False),
'reassign_mac': (bool, False),
'shutdown_command': (str, False),
Expand Down Expand Up @@ -1145,7 +1145,7 @@ class Qemu(PackerBuilder):
'net_device': (str, False),
'output_directory': (str, False),
'qemu_binary': (str, False),
'qemuargs': ([[str]], False),
'qemuargs': (validator.jagged_array(str), False),
}

def validate(self):
Expand Down Expand Up @@ -1239,8 +1239,8 @@ class VirtualboxIso(PackerBuilder):
'ssh_host_port_min': (int, False),
'ssh_host_port_max': (int, False),
'ssh_skip_nat_mapping': (validator.boolean, False),
'vboxmanage': ([[str]], False),
'vboxmanage_post': ([[str]], False),
'vboxmanage': (validator.jagged_array(str), False),
'vboxmanage_post': (validator.jagged_array(str), False),
'virtualbox_version_file': (str, False),
'vm_name': (str, False),
'vrdp_bind_address': (str, False),
Expand Down Expand Up @@ -1302,8 +1302,8 @@ class VirtualboxOvf(PackerBuilder):
'ssh_host_port_max': (int, False),
'ssh_skip_nat_mapping': (validator.boolean, False),
'target_path': (str, False),
'vboxmanage': ([[str]], False),
'vboxmanage_post': ([[str]], False),
'vboxmanage': (validator.jagged_array(str), False),
'vboxmanage_post': (validator.jagged_array(str), False),
'virtualbox_version_file': (str, False),
'vm_name': (str, False),
'vrdp_bind_address': (str, False),
Expand Down
24 changes: 24 additions & 0 deletions src/packerlicious/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,27 @@ def string_list_item_checker(x):
', '.join(str(j) for j in allowed_values))

return string_list_item_checker


def jagged_array(expected_type):
def jagged_array_checker(x):
# ensure outer list is present
if not isinstance(x, list):
raise ValueError("%r is not a valid array of array of %r" % (x, expected_type))

try:
l = list(x)
for sub_list in l:
# ensure inner sublist also exists
if not isinstance(sub_list, list):
raise ValueError("%r is not a valid array of array of %r" % (x, expected_type))

for value in sub_list:
if not isinstance(value, expected_type):
raise TypeError

return l
except(ValueError, TypeError):
raise ValueError("%r is not a valid array of array of %r" % (x, expected_type))

return jagged_array_checker
61 changes: 61 additions & 0 deletions tests/packerlicious/test_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,64 @@ def test_variable_no_duplicate_entries(self):
assert to_json == json.dumps(json.loads(expected_json), sort_keys=True, indent=2,
separators=(',', ': '))

def test_jagged_array_render(self):
expected_json = """
{
"builders": [
{
"boot_wait": "10s",
"floppy_files": [
""
],
"guest_additions_path": "VBoxGuestAdditions_{{.Version}}.iso",
"guest_os_type": "Ubuntu_64",
"http_directory": "",
"iso_checksum": "sha512",
"iso_checksum_type": "sha512",
"iso_url": "",
"ssh_port": 22,
"type": "virtualbox-iso",
"vboxmanage": [
[
"modifyvm", "{{.Name}}", "--memory", "1024"
],
[
"modifyvm", "{{.Name}}", "--vram", "36"
],
[
"modifyvm", "{{.Name}}", "--cpus", "1"
]
],
"virtualbox_version_file": ".vbox_version",
"vm_name": "my_name"
}
]
}
"""

t = Template()
t.add_builder(
builder.VirtualboxIso(
boot_wait="10s",
guest_os_type="Ubuntu_64",
http_directory="",
iso_url="",
iso_checksum_type="sha512",
iso_checksum="sha512",
ssh_port=22,
guest_additions_path="VBoxGuestAdditions_{{.Version}}.iso",
virtualbox_version_file=".vbox_version",
vm_name="my_name",
floppy_files=[""],
vboxmanage=[
"modifyvm {{.Name}} --memory 1024".split(),
"modifyvm {{.Name}} --vram 36".split(),
"modifyvm {{.Name}} --cpus 1".split()
]
# vboxmanage=[['modifyvm {{.Name}} --memory 1024', "modifyvm {{.Name}} --cpus 1"]]
)
)

to_json = t.to_json()
assert to_json == json.dumps(json.loads(expected_json), sort_keys=True, indent=2,
separators=(',', ': '))
51 changes: 36 additions & 15 deletions tests/packerlicious/test_validator.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Copyright (c) 2012-2013, Mark Peek <mark@peek.org>
# All rights reserved.
#
import unittest
import pytest

from thirdparty.troposphere import Parameter, Ref
Expand All @@ -11,28 +10,29 @@
from packerlicious.validator import s3_bucket_name, encoding, status
from packerlicious.validator import iam_path, iam_names, iam_role_name
from packerlicious.validator import iam_group_name, iam_user_name, elb_name
from packerlicious.validator import jagged_array
from packerlicious.validator import mutually_exclusive


class TestValidator(unittest.TestCase):
class TestValidator(object):

def test_boolean(self):
for x in [True, "True", "true", 1, "1"]:
self.assertEqual(boolean(x), "true", repr(x))
assert boolean(x) == "true", repr(x)
for x in [False, "False", "false", 0, "0"]:
self.assertEqual(boolean(x), "false", repr(x))
assert boolean(x) == "false", repr(x)
for x in ["000", "111", "abc"]:
with pytest.raises(ValueError):
boolean(x)

def test_integer(self):
self.assertEqual(integer(-1), -1)
self.assertEqual(integer("-1"), "-1")
self.assertEqual(integer(0), 0)
self.assertEqual(integer("0"), "0")
self.assertEqual(integer(65535), 65535)
self.assertEqual(integer("65535"), "65535")
self.assertEqual(integer(1.0), 1.0)
assert integer(-1) == -1
assert integer("-1") == "-1"
assert integer(0) == 0
assert integer("0") == "0"
assert integer(65535) == 65535
assert integer("65535") == "65535"
assert integer(1.0) == 1.0
with pytest.raises(ValueError):
integer("string")
with pytest.raises(ValueError):
Expand All @@ -42,9 +42,9 @@ def test_integer(self):

def test_integer_range(self):
between_ten_and_twenty = integer_range(10, 20)
self.assertEqual(between_ten_and_twenty(10), 10)
self.assertEqual(between_ten_and_twenty(15), 15)
self.assertEqual(between_ten_and_twenty(20), 20)
assert between_ten_and_twenty(10) == 10
assert between_ten_and_twenty(15) == 15
assert between_ten_and_twenty(20) == 20
for i in (-1, 9, 21, 1111111):
with pytest.raises(ValueError):
between_ten_and_twenty(i)
Expand Down Expand Up @@ -157,4 +157,25 @@ def test_mutually_exclusive(self):
with pytest.raises(ValueError):
mutually_exclusive('abc', ['a', 'b', 'c'], conds)


@pytest.mark.parametrize('test_value', [
'a_string_value',
1234,
['a_list_0', 'a_list_1'],
[['jagged_array_0,0'], 1234],
[['jagged_array_0,0'], [1234]],
])
def test_jagged_array_failure(self, test_value):
jagged_array_validator = jagged_array(str)
with pytest.raises(ValueError):
jagged_array_validator(test_value)

@pytest.mark.parametrize('test_value', [
[['jagged_array_0,0', 'jagged_array_0,1'], ['jagged_array_1,0']],
])
def test_jagged_array_success(self, test_value):
jagged_array_validator = jagged_array(str)
validator_return_value = jagged_array_validator(test_value)

for i, sub_list in enumerate(test_value):
for j, value in enumerate(sub_list):
assert validator_return_value[i][j] == value

0 comments on commit 6d478b0

Please sign in to comment.