test_node.py (ironic-17.0.2) | : | test_node.py (ironic-17.0.3) | ||
---|---|---|---|---|
skipping to change at line 20 | skipping to change at line 20 | |||
# License for the specific language governing permissions and limitations | # License for the specific language governing permissions and limitations | |||
# under the License. | # under the License. | |||
""" | """ | |||
Tests for the API /nodes/ methods. | Tests for the API /nodes/ methods. | |||
""" | """ | |||
import datetime | import datetime | |||
from http import client as http_client | from http import client as http_client | |||
import json | import json | |||
import os | import os | |||
import sys | ||||
import tempfile | import tempfile | |||
from unittest import mock | from unittest import mock | |||
from urllib import parse as urlparse | from urllib import parse as urlparse | |||
import fixtures | import fixtures | |||
from oslo_config import cfg | from oslo_config import cfg | |||
from oslo_utils import timeutils | from oslo_utils import timeutils | |||
from oslo_utils import uuidutils | from oslo_utils import uuidutils | |||
from testtools import matchers | from testtools import matchers | |||
skipping to change at line 142 | skipping to change at line 143 | |||
self.assertNotIn('conductor_group', data['nodes'][0]) | self.assertNotIn('conductor_group', data['nodes'][0]) | |||
self.assertNotIn('automated_clean', data['nodes'][0]) | self.assertNotIn('automated_clean', data['nodes'][0]) | |||
self.assertNotIn('protected', data['nodes'][0]) | self.assertNotIn('protected', data['nodes'][0]) | |||
self.assertNotIn('protected_reason', data['nodes'][0]) | self.assertNotIn('protected_reason', data['nodes'][0]) | |||
self.assertNotIn('owner', data['nodes'][0]) | self.assertNotIn('owner', data['nodes'][0]) | |||
self.assertNotIn('retired', data['nodes'][0]) | self.assertNotIn('retired', data['nodes'][0]) | |||
self.assertNotIn('retired_reason', data['nodes'][0]) | self.assertNotIn('retired_reason', data['nodes'][0]) | |||
self.assertNotIn('lessee', data['nodes'][0]) | self.assertNotIn('lessee', data['nodes'][0]) | |||
self.assertNotIn('network_data', data['nodes'][0]) | self.assertNotIn('network_data', data['nodes'][0]) | |||
@mock.patch.object(policy, 'check', autospec=True) | ||||
@mock.patch.object(policy, 'check_policy', autospec=True) | ||||
def test_one_field_specific_santization(self, mock_check_policy, | ||||
mock_check): | ||||
py_ver = sys.version_info | ||||
if py_ver.major == 3 and py_ver.minor == 6: | ||||
self.skipTest('Test fails to work on python 3.6 when ' | ||||
'matching mock.ANY.') | ||||
obj_utils.create_test_node(self.context, | ||||
chassis_id=self.chassis.id, | ||||
last_error='meow') | ||||
mock_check_policy.return_value = False | ||||
data = self.get_json( | ||||
'/nodes?fields=uuid,provision_state,maintenance,instance_uuid,' | ||||
'last_error', | ||||
headers={api_base.Version.string: str(api_v1.max_version())}) | ||||
self.assertIn('uuid', data['nodes'][0]) | ||||
self.assertIn('provision_state', data['nodes'][0]) | ||||
self.assertIn('maintenance', data['nodes'][0]) | ||||
self.assertIn('instance_uuid', data['nodes'][0]) | ||||
self.assertNotIn('driver_info', data['nodes'][0]) | ||||
mock_check_policy.assert_has_calls([ | ||||
mock.call('baremetal:node:get:filter_threshold', | ||||
mock.ANY, mock.ANY)]) | ||||
mock_check.assert_has_calls([ | ||||
mock.call('is_admin', mock.ANY, mock.ANY), | ||||
mock.call('show_password', mock.ANY, mock.ANY), | ||||
mock.call('show_instance_secrets', mock.ANY, mock.ANY), | ||||
# Last error is populated above and should trigger a check. | ||||
mock.call('baremetal:node:get:last_error', mock.ANY, mock.ANY), | ||||
mock.call().__bool__(), | ||||
mock.call().__bool__(), | ||||
]) | ||||
def test_get_one(self): | def test_get_one(self): | |||
node = obj_utils.create_test_node(self.context, | node = obj_utils.create_test_node(self.context, | |||
chassis_id=self.chassis.id) | chassis_id=self.chassis.id) | |||
data = self.get_json( | data = self.get_json( | |||
'/nodes/%s' % node.uuid, | '/nodes/%s' % node.uuid, | |||
headers={api_base.Version.string: str(api_v1.max_version())}) | headers={api_base.Version.string: str(api_v1.max_version())}) | |||
self.assertEqual(node.uuid, data['uuid']) | self.assertEqual(node.uuid, data['uuid']) | |||
self.assertIn('driver', data) | self.assertIn('driver', data) | |||
self.assertIn('driver_info', data) | self.assertIn('driver_info', data) | |||
self.assertEqual('******', data['driver_info']['fake_password']) | self.assertEqual('******', data['driver_info']['fake_password']) | |||
skipping to change at line 702 | skipping to change at line 737 | |||
self.assertIn('owner', data['nodes'][0]) | self.assertIn('owner', data['nodes'][0]) | |||
self.assertIn('lessee', data['nodes'][0]) | self.assertIn('lessee', data['nodes'][0]) | |||
# never expose the chassis_id | # never expose the chassis_id | |||
self.assertNotIn('chassis_id', data['nodes'][0]) | self.assertNotIn('chassis_id', data['nodes'][0]) | |||
self.assertNotIn('allocation_id', data['nodes'][0]) | self.assertNotIn('allocation_id', data['nodes'][0]) | |||
self.assertIn('allocation_uuid', data['nodes'][0]) | self.assertIn('allocation_uuid', data['nodes'][0]) | |||
self.assertIn('retired', data['nodes'][0]) | self.assertIn('retired', data['nodes'][0]) | |||
self.assertIn('retired_reason', data['nodes'][0]) | self.assertIn('retired_reason', data['nodes'][0]) | |||
self.assertIn('network_data', data['nodes'][0]) | self.assertIn('network_data', data['nodes'][0]) | |||
def test_detail_instance_uuid(self): | ||||
instance_uuid = '6eccd391-961c-4da5-b3c5-e2fa5cfbbd9d' | ||||
node = obj_utils.create_test_node( | ||||
self.context, | ||||
instance_uuid=instance_uuid) | ||||
data = self.get_json( | ||||
'/nodes/detail?instance_uuid=%s' % instance_uuid, | ||||
headers={api_base.Version.string: str(api_v1.max_version())}) | ||||
self.assertEqual(1, len(data['nodes'])) | ||||
self.assertEqual(node.uuid, data['nodes'][0]["uuid"]) | ||||
expected_fields = [ | ||||
'name', 'driver', 'driver_info', 'extra', 'chassis_uuid', | ||||
'reservation', 'maintenance', 'console_enabled', | ||||
'target_power_state', 'target_provision_state', | ||||
'provision_updated_at', 'inspection_finished_at', | ||||
'inspection_started_at', 'raid_config', 'target_raid_config', | ||||
'network_interface', 'resource_class', 'owner', 'lessee', | ||||
'storage_interface', 'traits', 'automated_clean', | ||||
'conductor_group', 'protected', 'protected_reason', | ||||
'retired', 'retired_reason', 'allocation_uuid', 'network_data' | ||||
] | ||||
for field in expected_fields: | ||||
self.assertIn(field, data['nodes'][0]) | ||||
for field in api_utils.V31_FIELDS: | ||||
self.assertIn(field, data['nodes'][0]) | ||||
# never expose the chassis_id | ||||
self.assertNotIn('chassis_id', data['nodes'][0]) | ||||
self.assertNotIn('allocation_id', data['nodes'][0]) | ||||
# no pagination marker should be present | ||||
self.assertNotIn('next', data) | ||||
@mock.patch.object(policy, 'authorize', spec=True) | ||||
def test_detail_instance_uuid_project_not_match(self, mock_authorize): | ||||
def mock_authorize_function(rule, target, creds): | ||||
if rule == 'baremetal:node:list_all': | ||||
raise exception.HTTPForbidden(resource='fake') | ||||
return True | ||||
mock_authorize.side_effect = mock_authorize_function | ||||
instance_uuid = '6eccd391-961c-4da5-b3c5-e2fa5cfbbd9d' | ||||
requestor_uuid = '46c0bf8a-846d-49a5-9724-5a61a5efa6bf' | ||||
obj_utils.create_test_node( | ||||
self.context, | ||||
owner='97879042-c0bf-4216-882a-66a7cbf2bd74', | ||||
instance_uuid=instance_uuid) | ||||
data = self.get_json( | ||||
'/nodes/detail?instance_uuid=%s' % instance_uuid, | ||||
headers={'X-Project-ID': requestor_uuid, | ||||
api_base.Version.string: str(api_v1.max_version())}) | ||||
self.assertEqual(0, len(data['nodes'])) | ||||
@mock.patch.object(policy, 'authorize', spec=True) | ||||
def test_detail_instance_uuid_project_match(self, mock_authorize): | ||||
def mock_authorize_function(rule, target, creds): | ||||
if rule == 'baremetal:node:list_all': | ||||
raise exception.HTTPForbidden(resource='fake') | ||||
return True | ||||
mock_authorize.side_effect = mock_authorize_function | ||||
instance_uuid = '6eccd391-961c-4da5-b3c5-e2fa5cfbbd9d' | ||||
requestor_uuid = '46c0bf8a-846d-49a5-9724-5a61a5efa6bf' | ||||
node = obj_utils.create_test_node( | ||||
self.context, | ||||
owner=requestor_uuid, | ||||
instance_uuid=instance_uuid) | ||||
data = self.get_json( | ||||
'/nodes/detail?instance_uuid=%s' % instance_uuid, | ||||
headers={'X-Project-ID': requestor_uuid, | ||||
api_base.Version.string: str(api_v1.max_version())}) | ||||
self.assertEqual(1, len(data['nodes'])) | ||||
# Assert we did get the node and it matched. | ||||
self.assertEqual(node.uuid, data['nodes'][0]["uuid"]) | ||||
self.assertEqual(node.owner, data['nodes'][0]["owner"]) | ||||
def test_detail_using_query(self): | def test_detail_using_query(self): | |||
node = obj_utils.create_test_node(self.context, | node = obj_utils.create_test_node(self.context, | |||
chassis_id=self.chassis.id) | chassis_id=self.chassis.id) | |||
data = self.get_json( | data = self.get_json( | |||
'/nodes?detail=True', | '/nodes?detail=True', | |||
headers={api_base.Version.string: str(api_v1.max_version())}) | headers={api_base.Version.string: str(api_v1.max_version())}) | |||
self.assertEqual(node.uuid, data['nodes'][0]["uuid"]) | self.assertEqual(node.uuid, data['nodes'][0]["uuid"]) | |||
self.assertIn('name', data['nodes'][0]) | self.assertIn('name', data['nodes'][0]) | |||
self.assertIn('driver', data['nodes'][0]) | self.assertIn('driver', data['nodes'][0]) | |||
self.assertIn('driver_info', data['nodes'][0]) | self.assertIn('driver_info', data['nodes'][0]) | |||
End of changes. 3 change blocks. | ||||
0 lines changed or deleted | 110 lines changed or added |