Skip to content

Commit

Permalink
move jagged array(an array of an array of things) validation into val…
Browse files Browse the repository at this point in the history
…idator.py
  • Loading branch information
mayn committed Mar 18, 2018
1 parent 2273a70 commit 602c3ce
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 172 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
12 changes: 1 addition & 11 deletions src/thirdparty/troposphere/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,17 +160,7 @@ def __setattr__(self, name, value):
# type checks (as above accept AWSHelperFn because
# we can't do the validation ourselves)
for v in value:
# If we're expecting a list of list with the same type
if isinstance(v, list):
# Double check that it's a list of list
if not all(isinstance(elem, list) for elem in value):
self._raise_type(name, v, expected_type)
# Make sure all elements in list are of the expected_type[0][0]
else:
for elem in v:
if not isinstance(elem, expected_type[0][0]):
self._raise_type(name, elem, expected_type[0][0])
elif not isinstance(v, tuple(expected_type)) \
if not isinstance(v, tuple(expected_type)) \
and not isinstance(v, AWSHelperFn):
self._raise_type(name, v, expected_type)
# Validated so assign it
Expand Down
191 changes: 55 additions & 136 deletions tests/packerlicious/test_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,145 +140,64 @@ def test_variable_no_duplicate_entries(self):
assert to_json == json.dumps(json.loads(expected_json), sort_keys=True, indent=2,
separators=(',', ': '))


expected_json_1 = """
{
"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}} --cpus 1"
]
],
"virtualbox_version_file": ".vbox_version",
"vm_name": ""
}
]
}
"""
expected_json_2 = """
{
"builders": [
def test_jagged_array_render(self):
expected_json = """
{
"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}}",
"--cpus 1"
]
],
"virtualbox_version_file": ".vbox_version",
"vm_name": ""
"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"
}
]
}
]
}
"""
assertion = 'type' if sys.version_info[0] < 3 else 'class'
exception_1 = "<class 'packerlicious.builder.VirtualboxIso'>: None.vboxmanage is <" + assertion \
+ " 'list'>, expected [[<" + assertion + " 'str'>]]"
exception_2 = "<class 'packerlicious.builder.VirtualboxIso'>: None.vboxmanage is <" + assertion\
+ " 'int'>, expected <" + assertion + " 'str'>"
@pytest.mark.parametrize('test_input,exception,expected', [
pytest.param(
[['modifyvm {{.Name}} --memory 1024'], ['modifyvm {{.Name}} --cpus 1']],
False,
expected_json_1,
marks=pytest.mark.basic
),
pytest.param(
[['modifyvm {{.Name}} --memory 1024'], ['modifyvm', '{{.Name}}', '--cpus 1']],
False,
expected_json_2,
marks=pytest.mark.basic
),
pytest.param(
[['modifyvm {{.Name}} --memory 1024'], 1],
True,
exception_1,
marks=pytest.mark.basic
),
pytest.param(
[['modifyvm {{.Name}} --memory 1024'], [1]],
True,
exception_2,
marks=pytest.mark.basic
)
])
def test_list_of_list_type_check(self, test_input, exception, expected):
"""

t = Template()
HTTP_DIR = ""
ISO_URL = ""
ISO_CHECKSUM_TYPE = "sha512"
ISO_CHECKSUM = "sha512"
VM_NAME = ""
VBOX_MANAGE=test_input
if exception:
with pytest.raises(TypeError) as excinfo:
t.add_builder(
builder.VirtualboxIso(
boot_wait="10s",
guest_os_type="Ubuntu_64",
http_directory=HTTP_DIR,
iso_url=ISO_URL,
iso_checksum_type=ISO_CHECKSUM_TYPE,
iso_checksum=ISO_CHECKSUM,
ssh_port=22,
guest_additions_path="VBoxGuestAdditions_{{.Version}}.iso",
virtualbox_version_file=".vbox_version",
vm_name=VM_NAME,
floppy_files=[""],
vboxmanage=VBOX_MANAGE
)
)
assert expected == str(excinfo.value)
else:
t.add_builder(
builder.VirtualboxIso(
boot_wait="10s",
guest_os_type="Ubuntu_64",
http_directory=HTTP_DIR,
iso_url=ISO_URL,
iso_checksum_type=ISO_CHECKSUM_TYPE,
iso_checksum=ISO_CHECKSUM,
ssh_port=22,
guest_additions_path="VBoxGuestAdditions_{{.Version}}.iso",
virtualbox_version_file=".vbox_version",
vm_name=VM_NAME,
floppy_files=[""],
vboxmanage=VBOX_MANAGE
)
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), sort_keys=True, indent=2,
)

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 602c3ce

Please sign in to comment.