From 8b31a22c2b1aecb9b10fc459b74f6f9cb940f903 Mon Sep 17 00:00:00 2001 From: Krysta Date: Thu, 14 Dec 2017 10:52:07 -0600 Subject: [PATCH] Unit Test for Validation Rules Updates Fixes some formatting in unit tests for validation rules as well as changes asserts to use re. Adds more tests coverage for validation rules. Change-Id: I23111ab57ac865969c6b1ea2e55565166e0f30b8 --- .../unit/test_validation_rule_mtu_rational.py | 15 +- .../unit/test_validation_rule_network_bond.py | 24 +- .../test_validation_rule_network_trunking.py | 22 +- ...st_validation_rule_storage_partitioning.py | 39 +- .../test_validation_rule_unique_network.py | 18 +- tests/yaml_samples/invalid_mtu.yaml | 8 +- ...age_partitioning_unassigned_partition.yaml | 440 ++++++++++++++++++ 7 files changed, 519 insertions(+), 47 deletions(-) create mode 100644 tests/yaml_samples/storage_partitioning_unassigned_partition.yaml diff --git a/tests/unit/test_validation_rule_mtu_rational.py b/tests/unit/test_validation_rule_mtu_rational.py index e2ee04f0..8ddfdd7b 100644 --- a/tests/unit/test_validation_rule_mtu_rational.py +++ b/tests/unit/test_validation_rule_mtu_rational.py @@ -15,7 +15,7 @@ from drydock_provisioner.orchestrator.orchestrator import Orchestrator from drydock_provisioner.orchestrator.validations.validator import Validator - +import re class TestMtu(object): def test_mtu(self, mocker, deckhand_ingester, drydock_state, input_files): @@ -44,8 +44,13 @@ class TestMtu(object): status, site_design = Orchestrator.get_effective_site(orch, design_ref) message_list = Validator.mtu_rational(site_design) - msg = message_list[0].to_dict() - assert 'Mtu Error' in msg.get('message') - assert msg.get('error') is True - assert len(message_list) == 1 + regex = re.compile('Mtu Error: Mtu must be between 1400 and 64000; on Network .+') + regex_1 = re.compile('Mtu Error: Mtu must be <= the parent Network Link; for Network .+') + + for msg in message_list: + msg = msg.to_dict() + assert msg.get('error') + assert regex.match(msg.get('message')) is not None or regex_1.match(msg.get('message')) is not None + + assert len(message_list) == 4 diff --git a/tests/unit/test_validation_rule_network_bond.py b/tests/unit/test_validation_rule_network_bond.py index 3baf3d6e..b764979d 100644 --- a/tests/unit/test_validation_rule_network_bond.py +++ b/tests/unit/test_validation_rule_network_bond.py @@ -15,11 +15,10 @@ from drydock_provisioner.orchestrator.orchestrator import Orchestrator from drydock_provisioner.orchestrator.validations.validator import Validator - +import re class TestRationalNetworkLinkBond(object): - def test_rational_network_bond( - self, mocker, deckhand_ingester, drydock_state, input_files): + def test_rational_network_bond(self, mocker, deckhand_ingester, drydock_state, input_files): input_file = input_files.join("rational_network_bond.yaml") design_ref = "file://%s" % str(input_file) @@ -35,8 +34,7 @@ class TestRationalNetworkLinkBond(object): assert msg.get('error') is False assert len(message_list) == 1 - def test_invalid_rational_network_bond( - self, mocker, deckhand_ingester, drydock_state, input_files): + def test_invalid_rational_network_bond(self, mocker, deckhand_ingester, drydock_state, input_files): input_file = input_files.join("invalid_rational_network_bond.yaml") design_ref = "file://%s" % str(input_file) @@ -47,14 +45,12 @@ class TestRationalNetworkLinkBond(object): message_list = Validator.rational_network_bond(site_design) - msg = message_list[0].to_dict() + regex = re.compile('Network Link Bonding Error: Down delay is less than mon rate on BaremetalNode .+') + regex_1 = re.compile('Network Link Bonding Error: Up delay is less than mon rate on BaremetalNode .+') - exp_msg = 'Network Link Bonding Error: Up delay' - assert exp_msg in msg.get('message') - assert msg.get('error') is True + for msg in message_list: + msg = msg.to_dict() + assert msg.get('error') is True + assert regex.match(msg.get('message')) is not None or regex_1.match(msg.get('message')) is not None - msg = message_list[1].to_dict() - - exp_msg = 'Network Link Bonding Error: Down delay' - assert exp_msg in msg.get('message') - assert msg.get('error') is True + assert len(message_list) == 2 diff --git a/tests/unit/test_validation_rule_network_trunking.py b/tests/unit/test_validation_rule_network_trunking.py index 8584c3ee..38fd80b6 100644 --- a/tests/unit/test_validation_rule_network_trunking.py +++ b/tests/unit/test_validation_rule_network_trunking.py @@ -15,11 +15,10 @@ from drydock_provisioner.orchestrator.orchestrator import Orchestrator from drydock_provisioner.orchestrator.validations.validator import Validator - +import re class TestRationalNetworkTrunking(object): - def test_rational_network_trunking( - self, deckhand_ingester, drydock_state, input_files): + def test_rational_network_trunking(self, deckhand_ingester, drydock_state, input_files): input_file = input_files.join("rational_network_trunking.yaml") design_ref = "file://%s" % str(input_file) @@ -34,8 +33,7 @@ class TestRationalNetworkTrunking(object): assert msg.get('message') == 'Rational Network Trunking' assert msg.get('error') is False - def test_invalid_rational_network_trunking( - self, deckhand_ingester, drydock_state, input_files): + def test_invalid_rational_network_trunking(self, deckhand_ingester, drydock_state, input_files): input_file = input_files.join("invalid_rational_network_trunking.yaml") design_ref = "file://%s" % str(input_file) @@ -46,7 +44,15 @@ class TestRationalNetworkTrunking(object): message_list = Validator.network_trunking_rational(site_design) - msg = message_list[0].to_dict() + regex = re.compile('Rational Network Trunking Error: Trunking mode is disabled, a trunking' + 'default_network must be defined; on NetworkLink .+') - assert 'Rational Network Trunking Error: ' in msg.get('message') - assert msg.get('error') is True + regex_1 = re.compile('Rational Network Trunking Error: If there is more than 1 allowed network,' + 'trunking mode must be enabled; on NetworkLink .+') + + for msg in message_list: + msg = msg.to_dict() + assert msg.get('error') + assert regex.match(msg.get('message')) is not None or regex_1.match(msg.get('message')) is not None + + assert len(message_list) == 2 diff --git a/tests/unit/test_validation_rule_storage_partitioning.py b/tests/unit/test_validation_rule_storage_partitioning.py index eac97185..53aa9b00 100644 --- a/tests/unit/test_validation_rule_storage_partitioning.py +++ b/tests/unit/test_validation_rule_storage_partitioning.py @@ -11,15 +11,14 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -"""Test Validation Rule Rational Network Trunking""" +"""Test Validation Rule Storage Partitioning""" from drydock_provisioner.orchestrator.orchestrator import Orchestrator from drydock_provisioner.orchestrator.validations.validator import Validator +import re - -class TestRationalNetworkTrunking(object): - def test_storage_partitioning( - self, deckhand_ingester, drydock_state, input_files): +class TestRationalStoragePartitioning(object): + def test_storage_partitioning(self, deckhand_ingester, drydock_state, input_files): input_file = input_files.join("storage_partitioning.yaml") design_ref = "file://%s" % str(input_file) @@ -35,8 +34,23 @@ class TestRationalNetworkTrunking(object): assert msg.get('message') == 'Storage Partitioning' assert msg.get('error') is False - def test_invalid_storage_partitioning( - self, deckhand_ingester, drydock_state, input_files): + def test_storage_partitioning_unassigned_partition(self, deckhand_ingester, drydock_state, input_files): + + input_file = input_files.join("storage_partitioning_unassigned_partition.yaml") + design_ref = "file://%s" % str(input_file) + + orch = Orchestrator(state_manager=drydock_state, ingester=deckhand_ingester) + + status, site_design = Orchestrator.get_effective_site(orch, design_ref) + + message_list = Validator.storage_partitioning(site_design) + msg = message_list[0].to_dict() + + assert len(message_list) == 1 + assert msg.get('message') == 'Storage Partitioning' + assert msg.get('error') is False + + def test_invalid_storage_partitioning(self, deckhand_ingester, drydock_state, input_files): input_file = input_files.join("invalid_storage_partitioning.yaml") design_ref = "file://%s" % str(input_file) @@ -46,8 +60,13 @@ class TestRationalNetworkTrunking(object): status, site_design = Orchestrator.get_effective_site(orch, design_ref) message_list = Validator.storage_partitioning(site_design) - msg = message_list[1].to_dict() - assert 'Storage Partitioning Error' in msg.get('message') - assert msg.get('error') is True + regex = re.compile('Storage Partitioning Error: A volume group must be assigned to a storage device or ' + 'partition; volume group .+ on BaremetalNode .+') + + for msg in message_list: + msg = msg.to_dict() + assert msg.get('error') + assert regex.match(msg.get('message')) is not None + assert len(message_list) == 2 diff --git a/tests/unit/test_validation_rule_unique_network.py b/tests/unit/test_validation_rule_unique_network.py index f2a42020..59e11de6 100644 --- a/tests/unit/test_validation_rule_unique_network.py +++ b/tests/unit/test_validation_rule_unique_network.py @@ -15,11 +15,10 @@ from drydock_provisioner.orchestrator.orchestrator import Orchestrator from drydock_provisioner.orchestrator.validations.validator import Validator - +import re class TestUniqueNetwork(object): - def test_unique_network(self, mocker, deckhand_ingester, drydock_state, - input_files): + def test_unique_network(self, mocker, deckhand_ingester, drydock_state, input_files): input_file = input_files.join("unique_network.yaml") design_ref = "file://%s" % str(input_file) @@ -35,8 +34,7 @@ class TestUniqueNetwork(object): assert msg.get('error') is False assert len(message_list) == 1 - def test_invalid_unique_network(self, mocker, deckhand_ingester, - drydock_state, input_files): + def test_invalid_unique_network(self, mocker, deckhand_ingester, drydock_state, input_files): input_file = input_files.join("invalid_unique_network.yaml") design_ref = "file://%s" % str(input_file) @@ -47,7 +45,11 @@ class TestUniqueNetwork(object): message_list = Validator.unique_network_check(site_design) - msg = message_list[0].to_dict() - assert 'Unique Network Error' in msg.get('message') - assert msg.get('error') is True + regex = re.compile('Unique Network Error: Allowed network .+ duplicated on NetworkLink .+ and NetworkLink .+') + + for msg in message_list: + msg = msg.to_dict() + assert msg.get('error') + assert regex.match(msg.get('message')) is not None + assert len(message_list) == 1 diff --git a/tests/yaml_samples/invalid_mtu.yaml b/tests/yaml_samples/invalid_mtu.yaml index a6273e93..4390702d 100644 --- a/tests/yaml_samples/invalid_mtu.yaml +++ b/tests/yaml_samples/invalid_mtu.yaml @@ -66,7 +66,9 @@ metadata: data: bonding: mode: disabled - mtu: 1500 +######################################## +# FAILS HERE: mtu of < 1400 + mtu: 700 linkspeed: auto trunking: mode: disabled @@ -188,7 +190,9 @@ metadata: application: 'drydock' data: vlan: '101' - mtu: 9000 +######################################## +# FAILS HERE: mtu of > 64000 + mtu: 74000 cidr: 172.16.2.0/24 ranges: - type: static diff --git a/tests/yaml_samples/storage_partitioning_unassigned_partition.yaml b/tests/yaml_samples/storage_partitioning_unassigned_partition.yaml new file mode 100644 index 00000000..5c1b12a5 --- /dev/null +++ b/tests/yaml_samples/storage_partitioning_unassigned_partition.yaml @@ -0,0 +1,440 @@ +#Copyright 2017 AT&T Intellectual Property. All other rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#################### +# +# bootstrap_seed.yaml - Site server design definition for physical layer +# +#################### +# version the schema in this file so consumers can rationally parse it +--- +schema: 'drydock/Region/v1' +metadata: + schema: 'metadata/Document/v1' + name: 'sitename' + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + tag_definitions: + - tag: 'test' + definition_type: 'lshw_xpath' + definition: "//node[@id=\"display\"]/'clock units=\"Hz\"' > 1000000000" + authorized_keys: + - | + ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDENeyO5hLPbLLQRZ0oafTYWs1ieo5Q+XgyZQs51Ju + jDGc8lKlWsg1/6yei2JewKMgcwG2Buu1eqU92Xn1SvMZLyt9GZURuBkyjcfVc/8GiU5QP1Of8B7CV0c + kfUpHWYJ17olTzT61Hgz10ioicBF6cjgQrLNcyn05xoaJHD2Vpf8Unxzi0YzA2e77yRqBo9jJVRaX2q + wUJuZrzb62x3zw8Knz6GGSZBn8xRKLaw1SKFpd1hwvL62GfqX5ZBAT1AYTZP1j8GcAoK8AFVn193SEU + vjSdUFa+RNWuJhkjBRfylJczIjTIFb5ls0jpbA3bMA9DE7lFKVQl6vVwFmiIVBI1 samplekey +--- +schema: 'drydock/NetworkLink/v1' +metadata: + schema: 'metadata/Document/v1' + name: oob + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + bonding: + mode: disabled + mtu: 1500 + linkspeed: 100full + trunking: + mode: disabled + default_network: oob + allowed_networks: + - oob +--- +schema: 'drydock/NetworkLink/v1' +metadata: + schema: 'metadata/Document/v1' + name: pxe + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + bonding: + mode: disabled + mtu: 1500 + linkspeed: auto + trunking: + mode: disabled + default_network: pxe + allowed_networks: + - pxe +--- +schema: 'drydock/NetworkLink/v1' +metadata: + schema: 'metadata/Document/v1' + name: gp + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + bonding: + mode: 802.3ad + hash: layer3+4 + peer_rate: slow + mtu: 9000 + linkspeed: auto + trunking: + mode: 802.1q + default_network: mgmt + allowed_networks: + - public + - mgmt +--- +schema: 'drydock/Rack/v1' +metadata: + schema: 'metadata/Document/v1' + name: rack1 + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + tor_switches: + switch01name: + mgmt_ip: 1.1.1.1 + sdn_api_uri: polo+https://polo-api.web.att.com/switchmgmt?switch=switch01name + switch02name: + mgmt_ip: 1.1.1.2 + sdn_api_uri: polo+https://polo-api.web.att.com/switchmgmt?switch=switch02name + location: + clli: HSTNTXMOCG0 + grid: EG12 + local_networks: + - pxe-rack1 +--- +schema: 'drydock/Network/v1' +metadata: + schema: 'metadata/Document/v1' + name: oob + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + cidr: 172.16.100.0/24 + ranges: + - type: static + start: 172.16.100.15 + end: 172.16.100.254 + dns: + domain: ilo.sitename.att.com + servers: 172.16.100.10 +--- +schema: 'drydock/Network/v1' +metadata: + schema: 'metadata/Document/v1' + name: pxe + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + dhcp_relay: + self_ip: 172.16.0.4 + upstream_target: 172.16.5.5 + mtu: 1500 + cidr: 172.16.0.0/24 + ranges: + - type: dhcp + start: 172.16.0.5 + end: 172.16.0.254 + dns: + domain: admin.sitename.att.com + servers: 172.16.0.10 +--- +schema: 'drydock/Network/v1' +metadata: + schema: 'metadata/Document/v1' + name: mgmt + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + vlan: '100' + mtu: 1500 + cidr: 172.16.1.0/24 + ranges: + - type: static + start: 172.16.1.15 + end: 172.16.1.254 + routes: + - subnet: 0.0.0.0/0 + gateway: 172.16.1.1 + metric: 10 + dns: + domain: mgmt.sitename.example.com + servers: 172.16.1.9,172.16.1.10 +--- +schema: 'drydock/Network/v1' +metadata: + schema: 'metadata/Document/v1' + name: private + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + vlan: '101' + mtu: 9000 + cidr: 172.16.2.0/24 + ranges: + - type: static + start: 172.16.2.15 + end: 172.16.2.254 + dns: + domain: priv.sitename.example.com + servers: 172.16.2.9,172.16.2.10 +--- +schema: 'drydock/Network/v1' +metadata: + schema: 'metadata/Document/v1' + name: public + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + vlan: '102' + mtu: 1500 + cidr: 172.16.3.0/24 + ranges: + - type: static + start: 172.16.3.15 + end: 172.16.3.254 + routes: + - subnet: 0.0.0.0/0 + gateway: 172.16.3.1 + metric: 10 + dns: + domain: sitename.example.com + servers: 8.8.8.8 +--- +schema: 'drydock/HostProfile/v1' +metadata: + schema: 'metadata/Document/v1' + name: defaults + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + oob: + type: ipmi + network: oob + account: admin + credential: admin + storage: + physical_devices: + sda: + labels: + role: rootdisk + partitions: + - name: root + size: 20g + bootable: true + - name: boot + size: 1g + bootable: false + sdb: + volume_group: 'log_vg' + volume_groups: + log_vg: + logical_volumes: + - name: 'log_lv' + size: '500m' + filesystem: + mountpoint: '/var/log' + fstype: 'xfs' + mount_options: 'defaults' + platform: + image: ubuntu_16.04 + kernel: generic + kernel_params: + quiet: true + console: ttyS2 + metadata: + owner_data: + foo: bar +--- +schema: 'drydock/HostProfile/v1' +metadata: + schema: 'metadata/Document/v1' + name: 'k8-node' + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + host_profile: defaults + hardware_profile: HPGen9v3 + primary_network: mgmt + interfaces: + pxe: + device_link: pxe + labels: + noconfig: true + slaves: + - prim_nic01 + networks: + - pxe + bond0: + device_link: gp + slaves: + - prim_nic01 + - prim_nic02 + networks: + - mgmt + - private + metadata: + tags: + - 'test' +--- +schema: 'drydock/BaremetalNode/v1' +metadata: + schema: 'metadata/Document/v1' + name: controller01 + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + host_profile: k8-node + interfaces: + bond0: + networks: + - '!private' + addressing: + - network: pxe + address: dhcp + - network: mgmt + address: 172.16.1.20 + - network: public + address: 172.16.3.20 + - network: oob + address: 172.16.100.20 + metadata: + rack: rack1 +--- +schema: 'drydock/BaremetalNode/v1' +metadata: + schema: 'metadata/Document/v1' + name: compute01 + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + host_profile: k8-node + addressing: + - network: pxe + address: dhcp + - network: mgmt + address: 172.16.1.21 + - network: private + address: 172.16.2.21 + - network: oob + address: 172.16.100.21 + metadata: + rack: rack2 +--- +schema: 'drydock/HardwareProfile/v1' +metadata: + schema: 'metadata/Document/v1' + name: HPGen9v3 + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + vendor: HP + generation: '8' + hw_version: '3' + bios_version: '2.2.3' + boot_mode: bios + bootstrap_protocol: pxe + pxe_interface: 0 + device_aliases: + prim_nic01: + address: '0000:00:03.0' + dev_type: '82540EM Gigabit Ethernet Controller' + bus_type: 'pci' + prim_nic02: + address: '0000:00:04.0' + dev_type: '82540EM Gigabit Ethernet Controller' + bus_type: 'pci' + primary_boot: + address: '2:0.0.0' + dev_type: 'VBOX HARDDISK' + bus_type: 'scsi' +--- +schema: 'drydock/BootAction/v1' +metadata: + schema: 'metadata/Document/v1' + name: helloworld + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + assets: + - path: /var/tmp/hello.sh + type: file + permissions: '555' + data: |- + IyEvYmluL2Jhc2gKCmVjaG8gJ0hlbGxvIFdvcmxkISAtZnJvbSB7eyBub2RlLmhvc3RuYW1lIH19 + Jwo= + data_pipeline: + - base64_decode + - utf8_decode + - template + - path: /lib/systemd/system/hello.service + type: unit + permissions: '600' + data: |- + W1VuaXRdCkRlc2NyaXB0aW9uPUhlbGxvIFdvcmxkCgpbU2VydmljZV0KVHlwZT1vbmVzaG90CkV4 + ZWNTdGFydD0vdmFyL3RtcC9oZWxsby5zaAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIu + dGFyZ2V0Cg== + data_pipeline: + - base64_decode + - utf8_decode +--- +schema: 'drydock/BootAction/v1' +metadata: + schema: 'metadata/Document/v1' + name: hw_filtered + storagePolicy: 'cleartext' + labels: + application: 'drydock' +data: + node_filter: + filter_set_type: 'union' + filter_set: + - filter_type: 'union' + node_names: + - 'compute01' + assets: + - path: /var/tmp/hello.sh + type: file + permissions: '555' + data: |- + IyEvYmluL2Jhc2gKCmVjaG8gJ0hlbGxvIFdvcmxkISAtZnJvbSB7eyBub2RlLmhvc3RuYW1lIH19 + Jwo= + data_pipeline: + - base64_decode + - utf8_decode + - template + - path: /lib/systemd/system/hello.service + type: unit + permissions: '600' + data: |- + W1VuaXRdCkRlc2NyaXB0aW9uPUhlbGxvIFdvcmxkCgpbU2VydmljZV0KVHlwZT1vbmVzaG90CkV4 + ZWNTdGFydD0vdmFyL3RtcC9oZWxsby5zaAoKW0luc3RhbGxdCldhbnRlZEJ5PW11bHRpLXVzZXIu + dGFyZ2V0Cg== + data_pipeline: + - base64_decode + - utf8_decode +...