# Copyright (c) 2016 Mirantis, Inc. # # 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. import json import jsonschema from tempest.lib.common.utils import data_utils from ironicclient.tests.functional import base def _validate_json(json_response, schema): """Verify JSON is valid. :param json_response: JSON response from CLI :type json_response: string :param schema: expected schema of response :type json_response: dictionary """ json_response = json.loads(json_response) jsonschema.validate(json_response, schema) class TestNodeJsonResponse(base.FunctionalTestBase): """Test JSON responses for node commands.""" node_schema = { "type": "object", "properties": { "target_power_state": {"type": ["string", "null"]}, "extra": {"type": "object"}, "last_error": {"type": ["string", "null"]}, "updated_at": {"type": ["string", "null"]}, "maintenance_reason": {"type": ["string", "null"]}, "provision_state": {"type": "string"}, "clean_step": {"type": "object"}, "deploy_step": {"type": "object"}, "uuid": {"type": "string"}, "console_enabled": {"type": "boolean"}, "target_provision_state": {"type": ["string", "null"]}, "raid_config": {"type": "object"}, "provision_updated_at": {"type": ["string", "null"]}, "maintenance": {"type": "boolean"}, "target_raid_config": {"type": "object"}, "inspection_started_at": {"type": ["string", "null"]}, "inspection_finished_at": {"type": ["string", "null"]}, "power_state": {"type": ["string", "null"]}, "driver": {"type": "string"}, "reservation": {"type": ["string", "null"]}, "properties": {"type": "object"}, "instance_uuid": {"type": ["string", "null"]}, "name": {"type": ["string", "null"]}, "driver_info": {"type": "object"}, "created_at": {"type": "string"}, "driver_internal_info": {"type": "object"}, "chassis_uuid": {"type": ["string", "null"]}, "instance_info": {"type": "object"} }, "patternProperties": { ".*_interface$": {"type": ["string", "null"]} }, "additionalProperties": True } def setUp(self): super(TestNodeJsonResponse, self).setUp() self.node = self.create_node() def test_node_list_json(self): """Test JSON response for nodes list.""" schema = { "type": "array", "items": { "type": "object", "properties": { "instance_uuid": {"type": ["string", "null"]}, "maintenance": {"type": "boolean"}, "name": {"type": ["string", "null"]}, "power_state": {"type": ["string", "null"]}, "provision_state": {"type": "string"}, "uuid": {"type": "string"}}} } response = self.ironic('node-list', flags='--json', params='', parse=False) _validate_json(response, schema) def test_node_show_json(self): """Test JSON response for node show.""" response = self.ironic('node-show', flags='--json', params='{0}' .format(self.node['uuid']), parse=False) _validate_json(response, self.node_schema) def test_node_validate_json(self): """Test JSON response for node validation.""" schema = { "type": "array", "items": { "type": "object", "properties": { "interface": {"type": ["string", "null"]}, "result": {"type": ["boolean", "null"]}, "reason": {"type": ["string", "null"]}}} } response = self.ironic('node-validate', flags='--json', params='{0}'.format(self.node['uuid']), parse=False) _validate_json(response, schema) def test_node_show_states_json(self): """Test JSON response for node show states.""" schema = { "type": "object", "properties": { "target_power_state": {"type": ["string", "null"]}, "target_provision_state": {"type": ["string", "null"]}, "last_error": {"type": ["string", "null"]}, "console_enabled": {"type": "boolean"}, "provision_updated_at": {"type": ["string", "null"]}, "power_state": {"type": ["string", "null"]}, "provision_state": {"type": "string"} } } response = self.ironic('node-show-states', flags='--json', params='{0}'.format(self.node['uuid']), parse=False) _validate_json(response, schema) def test_node_create_json(self): """Test JSON response for node creation.""" schema = { "type": "object", "properties": { "uuid": {"type": "string"}, "driver_info": {"type": "object"}, "extra": {"type": "object"}, "driver": {"type": "string"}, "chassis_uuid": {"type": ["string", "null"]}, "properties": {"type": "object"}, "name": {"type": ["string", "null"]}, } } node_name = 'nodejson' response = self.ironic( 'node-create', flags='--json', params='-d fake-hardware -n {0}'.format(node_name), parse=False) self.addCleanup(self.delete_node, node_name) _validate_json(response, schema) def test_node_update_json(self): """Test JSON response for node update.""" node_name = data_utils.rand_name('test') response = self.ironic('node-update', flags='--json', params='{0} add name={1}' .format(self.node['uuid'], node_name), parse=False) _validate_json(response, self.node_schema) class TestDriverJsonResponse(base.FunctionalTestBase): """Test JSON responses for driver commands.""" def test_driver_list_json(self): """Test JSON response for drivers list.""" schema = { "type": "array", "items": { "type": "object", "properties": { "name": {"type": "string"}, "hosts": {"type": "string"}, }} } response = self.ironic('driver-list', flags='--json', parse=False) _validate_json(response, schema) def test_driver_show_json(self): """Test JSON response for driver show.""" schema = { "type": "object", "properties": { "name": {"type": "string"}, "hosts": { "type": "array", "items": {"type": "string"}} } } drivers_names = self.get_drivers_names() for driver in drivers_names: response = self.ironic('driver-show', flags='--json', params='{0}'.format(driver), parse=False) _validate_json(response, schema) def test_driver_properties_json(self): """Test JSON response for driver properties.""" schema = { "type": "object", "additionalProperties": {"type": "string"} } drivers_names = self.get_drivers_names() for driver in drivers_names: response = self.ironic('driver-properties', flags='--json', params='{0}'.format(driver), parse=False) _validate_json(response, schema) class TestChassisJsonResponse(base.FunctionalTestBase): """Test JSON responses for chassis commands.""" chassis_schema = { "type": "object", "properties": { "uuid": {"type": "string"}, "updated_at": {"type": ["string", "null"]}, "created_at": {"type": "string"}, "description": {"type": ["string", "null"]}, "extra": {"type": "object"}} } def setUp(self): super(TestChassisJsonResponse, self).setUp() self.chassis = self.create_chassis() def test_chassis_list_json(self): """Test JSON response for chassis list.""" schema = { "type": "array", "items": { "type": "object", "properties": { "uuid": {"type": "string"}, "description": {"type": ["string", "null"]}} } } response = self.ironic('chassis-list', flags='--json', parse=False) _validate_json(response, schema) def test_chassis_show_json(self): """Test JSON response for chassis show.""" response = self.ironic('chassis-show', flags='--json', params='{0}'.format(self.chassis['uuid']), parse=False) _validate_json(response, self.chassis_schema) def test_chassis_create_json(self): """Test JSON response for chassis create.""" response = self.ironic('chassis-create', flags='--json', parse=False) _validate_json(response, self.chassis_schema) def test_chassis_update_json(self): """Test JSON response for chassis update.""" response = self.ironic( 'chassis-update', flags='--json', params='{0} {1} {2}'.format( self.chassis['uuid'], 'add', 'description=test-chassis'), parse=False) _validate_json(response, self.chassis_schema) def test_chassis_node_list_json(self): """Test JSON response for chassis-node-list command.""" schema = { "type": "array", "items": { "type": "object", "properties": { "instance_uuid": {"type": ["string", "null"]}, "maintenance": {"type": "boolean"}, "name": {"type": ["string", "null"]}, "power_state": {"type": ["string", "null"]}, "provision_state": {"type": "string"}, "uuid": {"type": "string"}}} } self.node = self.create_node() self.update_node(self.node['uuid'], 'add chassis_uuid={0}' .format(self.chassis['uuid'])) response = self.ironic('chassis-node-list', flags='--json', params='{0}'.format(self.chassis['uuid']), parse=False) _validate_json(response, schema)