diff --git a/devstack/plugin.sh b/devstack/plugin.sh index 246bf2e6a..9e1dd0d11 100644 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -195,7 +195,7 @@ function inspector_configure_auth_for { inspector_iniset $1 user_domain_id default inspector_iniset $1 project_domain_id default inspector_iniset $1 cafile $SSL_BUNDLE_FILE - inspector_iniset $1 os_region $REGION_NAME + inspector_iniset $1 region_name $REGION_NAME } function is_dnsmasq_filter_required { diff --git a/example.conf b/example.conf index 0b341f22f..60dd06b4e 100644 --- a/example.conf +++ b/example.conf @@ -15,7 +15,9 @@ # Authentication method used on the ironic-inspector API. Either # "noauth" or "keystone" are currently valid options. "noauth" will # disable all authentication. (string value) -# Allowed values: keystone, noauth +# Possible values: +# keystone - +# noauth - #auth_strategy = keystone # Timeout after which introspection is considered failed, set to 0 to @@ -414,8 +416,16 @@ # Authentication URL (string value) #auth_url = -# Method to use for authentication: noauth or keystone. (string value) -# Allowed values: keystone, noauth +# DEPRECATED: Method to use for authentication: noauth or keystone. +# (string value) +# Possible values: +# keystone - +# noauth - +# This option is deprecated for removal. +# Its value may be silently ignored in the future. +# Reason: Use [ironic]/auth_type, for noauth case set +# [ironic]/auth_type to `none` and specify ironic API URL via +# [ironic]/endpoint_override option. #auth_strategy = keystone # Authentication type to load (string value) @@ -445,28 +455,60 @@ # Domain name to scope to (string value) #domain_name = +# Always use this endpoint URL for requests for this client. NOTE: The +# unversioned endpoint should be specified here; to request a +# particular API version, use the `version`, `min-version`, and/or +# `max-version` options. (string value) +#endpoint_override = + # Verify HTTPS connections. (boolean value) #insecure = false -# Ironic API URL, used to set Ironic API URL when auth_strategy option -# is noauth to work with standalone Ironic without keystone. (string -# value) +# DEPRECATED: Ironic API URL, used to set Ironic API URL when +# auth_strategy option is noauth or auth_type is "none" to work with +# standalone Ironic without keystone. (string value) +# This option is deprecated for removal. +# Its value may be silently ignored in the future. +# Reason: Use [ironic]/endpoint_override option to set a specific +# ironic API url. #ironic_url = http://localhost:6385/ # PEM encoded client certificate key file (string value) #keyfile = +# The maximum major version of a given API, intended to be used as the +# upper bound of a range with min_version. Mutually exclusive with +# version. (string value) +#max_version = + # Maximum number of retries in case of conflict error (HTTP 409). # (integer value) #max_retries = 30 -# Ironic endpoint type. (string value) +# The minimum major version of a given API, intended to be used as the +# lower bound of a range with max_version. Mutually exclusive with +# version. If min_version is given with no max_version it is as if max +# version is "latest". (string value) +#min_version = + +# DEPRECATED: Ironic endpoint type. (string value) +# This option is deprecated for removal. +# Its value may be silently ignored in the future. +# Reason: Use [ironic]/valid_interfaces option to specify endpoint +# interfaces. #os_endpoint_type = internalURL -# Keystone region used to get Ironic endpoints. (string value) +# DEPRECATED: Keystone region used to get Ironic endpoints. (string +# value) +# This option is deprecated for removal. +# Its value may be silently ignored in the future. +# Reason: Use [ironic]/region_name option instead to configure region. #os_region = -# Ironic service type. (string value) +# DEPRECATED: Ironic service type. (string value) +# This option is deprecated for removal. +# Its value may be silently ignored in the future. +# Reason: Use [ironic]/service_type option to set a specific type. #os_service_type = baremetal # User's password (string value) @@ -486,10 +528,19 @@ # Deprecated group/name - [ironic]/tenant_name #project_name = +# The default region_name for endpoint URL discovery. (string value) +#region_name = + # Interval between retries in case of conflict error (HTTP 409). # (integer value) #retry_interval = 2 +# The default service_name for endpoint URL discovery. (string value) +#service_name = + +# The default service_type for endpoint URL discovery. (string value) +#service_type = baremetal + # Tenant ID (string value) #tenant_id = @@ -515,6 +566,15 @@ # Deprecated group/name - [ironic]/user_name #username = +# List of interfaces, in order of preference, for endpoint URL. (list +# value) +#valid_interfaces = internal,public + +# Minimum Major API version within a given Major API version for +# endpoint URL discovery. Mutually exclusive with min_version and +# max_version (string value) +#version = + [keystone_authtoken] @@ -627,7 +687,10 @@ # encrypted and authenticated in the cache. If the value is not one of # these options or empty, auth_token will raise an exception on # initialization. (string value) -# Allowed values: None, MAC, ENCRYPT +# Possible values: +# None - +# MAC - +# ENCRYPT - #memcache_security_strategy = None # (Optional, mandatory if memcache_security_strategy is defined) This @@ -725,6 +788,14 @@ # From oslo.policy # +# This option controls whether or not to enforce scope when evaluating +# policies. If ``True``, the scope of the token used in the request is +# compared to the ``scope_types`` of the policy being enforced. If the +# scopes do not match, an ``InvalidScope`` exception will be raised. +# If ``False``, a message will be logged informing operators that +# policies are being invoked with mismatching scope. (boolean value) +#enforce_scope = false + # The file that defines policies. (string value) #policy_file = policy.json @@ -741,7 +812,9 @@ # Content Type to send and receive data for REST based policy check # (string value) -# Allowed values: application/x-www-form-urlencoded, application/json +# Possible values: +# application/x-www-form-urlencoded - +# application/json - #remote_content_type = application/x-www-form-urlencoded # server identity verification for REST based policy check (boolean @@ -783,14 +856,21 @@ # IP addresses), pxe (only MAC address of NIC node PXE booted from, # falls back to "active" if PXE MAC is not supplied by the ramdisk). # (string value) -# Allowed values: all, active, pxe, disabled +# Possible values: +# all - +# active - +# pxe - +# disabled - #add_ports = pxe # Which ports (already present on a node) to keep after introspection. # Possible values: all (do not delete anything), present (keep ports # which MACs were present in introspection data), added (keep only # MACs that we added during introspection). (string value) -# Allowed values: all, present, added +# Possible values: +# all - +# present - +# added - #keep_ports = all # Whether to overwrite existing values in node database. Disable this @@ -827,7 +907,9 @@ # Method for storing introspection data. If set to 'none', # introspection data will not be stored. (string value) -# Allowed values: none, swift +# Possible values: +# none - +# swift - #store_data = none # Name of the key to store the location of stored data in the extra @@ -908,23 +990,50 @@ # Domain name to scope to (string value) #domain_name = +# Always use this endpoint URL for requests for this client. NOTE: The +# unversioned endpoint should be specified here; to request a +# particular API version, use the `version`, `min-version`, and/or +# `max-version` options. (string value) +#endpoint_override = + # Verify HTTPS connections. (boolean value) #insecure = false # PEM encoded client certificate key file (string value) #keyfile = +# The maximum major version of a given API, intended to be used as the +# upper bound of a range with min_version. Mutually exclusive with +# version. (string value) +#max_version = + # Maximum number of times to retry a Swift request, before failing. # (integer value) #max_retries = 2 -# Swift endpoint type. (string value) +# The minimum major version of a given API, intended to be used as the +# lower bound of a range with max_version. Mutually exclusive with +# version. If min_version is given with no max_version it is as if max +# version is "latest". (string value) +#min_version = + +# DEPRECATED: Swift endpoint type. (string value) +# This option is deprecated for removal. +# Its value may be silently ignored in the future. +# Reason: Use [swift]/valid_interfaces option to specify endpoint +# interfaces. #os_endpoint_type = internalURL -# Keystone region to get endpoint for. (string value) +# DEPRECATED: Keystone region to get endpoint for. (string value) +# This option is deprecated for removal. +# Its value may be silently ignored in the future. +# Reason: Use [swift]/region_name option to configure region. #os_region = -# Swift service type. (string value) +# DEPRECATED: Swift service type. (string value) +# This option is deprecated for removal. +# Its value may be silently ignored in the future. +# Reason: Use [swift]/service_type option to set specific service type #os_service_type = object-store # User's password (string value) @@ -944,6 +1053,15 @@ # Deprecated group/name - [swift]/tenant_name #project_name = +# The default region_name for endpoint URL discovery. (string value) +#region_name = + +# The default service_name for endpoint URL discovery. (string value) +#service_name = + +# The default service_type for endpoint URL discovery. (string value) +#service_type = object-store + # Tenant ID (string value) #tenant_id = @@ -968,3 +1086,12 @@ # Username (string value) # Deprecated group/name - [swift]/user_name #username = + +# List of interfaces, in order of preference, for endpoint URL. (list +# value) +#valid_interfaces = internal,public + +# Minimum Major API version within a given Major API version for +# endpoint URL discovery. Mutually exclusive with min_version and +# max_version (string value) +#version = diff --git a/ironic_inspector/common/ironic.py b/ironic_inspector/common/ironic.py index 7541453fe..e9374ad2b 100644 --- a/ironic_inspector/common/ironic.py +++ b/ironic_inspector/common/ironic.py @@ -82,29 +82,42 @@ def get_ipmi_address(node): def get_client(token=None, api_version=DEFAULT_IRONIC_API_VERSION): # pragma: no cover """Get Ironic client instance.""" + global IRONIC_SESSION + if not IRONIC_SESSION: + IRONIC_SESSION = keystone.get_session('ironic') + + args = { + 'os_ironic_api_version': api_version, + 'max_retries': CONF.ironic.max_retries, + 'retry_interval': CONF.ironic.retry_interval} + + adapter_opts = dict() + # NOTE: To support standalone ironic without keystone + # TODO(pas-ha) remove handling of deprecated opts in Rocky + # TODO(pas-ha) rewrite when ironicclient natively supports 'none' auth + # via sessions https://review.openstack.org/#/c/359061/ if CONF.ironic.auth_strategy == 'noauth': - args = {'token': 'noauth', - 'endpoint': CONF.ironic.ironic_url} + CONF.set_override('auth_type', 'none', group='ironic') else: - global IRONIC_SESSION - if not IRONIC_SESSION: - IRONIC_SESSION = keystone.get_session('ironic') + # TODO(pas-ha) use service auth with incoming token if token is None: - args = {'session': IRONIC_SESSION, - 'region_name': CONF.ironic.os_region} + args['session'] = IRONIC_SESSION else: - ironic_url = IRONIC_SESSION.get_endpoint( - service_type=CONF.ironic.os_service_type, - endpoint_type=CONF.ironic.os_endpoint_type, - region_name=CONF.ironic.os_region - ) - args = {'token': token, - 'endpoint': ironic_url} - args['os_ironic_api_version'] = api_version - args['max_retries'] = CONF.ironic.max_retries - args['retry_interval'] = CONF.ironic.retry_interval - return client.Client(1, **args) + args['token'] = token + + # TODO(pas-ha): remove handling of deprecated options in Rocky + if CONF.ironic.os_region and not CONF.ironic.region_name: + adapter_opts['region_name'] = CONF.ironic.os_region + if (CONF.ironic.auth_type == 'none' and + not CONF.ironic.endpoint_override and + CONF.ironic.ironic_url): + adapter_opts['endpoint_override'] = CONF.ironic.ironic_url + + adapter = keystone.get_adapter('ironic', session=IRONIC_SESSION, + **adapter_opts) + endpoint = adapter.get_endpoint() + return client.Client(1, endpoint, **args) def check_provision_state(node): diff --git a/ironic_inspector/common/keystone.py b/ironic_inspector/common/keystone.py index 52dc6afc9..4dae71dfa 100644 --- a/ironic_inspector/common/keystone.py +++ b/ironic_inspector/common/keystone.py @@ -18,12 +18,18 @@ from oslo_config import cfg CONF = cfg.CONF +DEFAULT_VALID_INTERFACES = ['internal', 'public'] -def register_auth_opts(group): +# TODO(pas-ha) set default values in conf.opts.set_defaults() +def register_auth_opts(group, service_type): loading.register_session_conf_options(CONF, group) loading.register_auth_conf_options(CONF, group) CONF.set_default('auth_type', default='password', group=group) + loading.register_adapter_conf_options(CONF, group) + CONF.set_default('valid_interfaces', DEFAULT_VALID_INTERFACES, + group=group) + CONF.set_default('service_type', service_type, group=group) def get_session(group): @@ -33,8 +39,13 @@ def get_session(group): return session -def add_auth_options(options): +def get_adapter(group, **adapter_kwargs): + return loading.load_adapter_from_conf_options(CONF, group, + **adapter_kwargs) + +# TODO(pas-ha) set default values in conf.opts.set_defaults() +def add_auth_options(options, service_type): def add_options(opts, opts_to_add): for new_opt in opts_to_add: for opt in opts: @@ -52,5 +63,10 @@ def add_auth_options(options): plugin = loading.get_plugin_loader(name) add_options(opts, loading.get_auth_plugin_conf_options(plugin)) add_options(opts, loading.get_session_conf_options()) + adapter_opts = loading.get_adapter_conf_options( + include_deprecated=False) + cfg.set_defaults(adapter_opts, service_type=service_type, + valid_interfaces=DEFAULT_VALID_INTERFACES) + add_options(opts, adapter_opts) opts.sort(key=lambda x: x.name) return opts diff --git a/ironic_inspector/common/swift.py b/ironic_inspector/common/swift.py index 5bf2c8d1b..a06e49dce 100644 --- a/ironic_inspector/common/swift.py +++ b/ironic_inspector/common/swift.py @@ -51,7 +51,21 @@ class SwiftAPI(object): if not SWIFT_SESSION: SWIFT_SESSION = keystone.get_session('swift') - self.connection = swift_client.Connection(session=SWIFT_SESSION) + adapter_opts = dict() + # TODO(pas-ha): remove handling deprecated options in Rocky + if CONF.swift.os_region and not CONF.swift.region_name: + adapter_opts['region_name'] = CONF.swift.os_region + + adapter = keystone.get_adapter('swift', session=SWIFT_SESSION, + **adapter_opts) + + # TODO(pas-ha) reverse-construct SSL-related session options here + params = { + 'os_options': { + 'object_storage_url': adapter.get_endpoint()}} + + self.connection = swift_client.Connection(session=SWIFT_SESSION, + **params) def create_object(self, object, data, container=CONF.swift.container, headers=None): diff --git a/ironic_inspector/conf/ironic.py b/ironic_inspector/conf/ironic.py index ea26371cc..257174571 100644 --- a/ironic_inspector/conf/ironic.py +++ b/ironic_inspector/conf/ironic.py @@ -18,27 +18,45 @@ from ironic_inspector.common import keystone IRONIC_GROUP = 'ironic' +SERVICE_TYPE = 'baremetal' _OPTS = [ cfg.StrOpt('os_region', - help=_('Keystone region used to get Ironic endpoints.')), + help=_('Keystone region used to get Ironic endpoints.'), + deprecated_for_removal=True, + deprecated_reason=_("Use [ironic]/region_name option instead " + "to configure region.")), cfg.StrOpt('auth_strategy', default='keystone', choices=('keystone', 'noauth'), help=_('Method to use for authentication: noauth or ' - 'keystone.')), + 'keystone.'), + deprecated_for_removal=True, + deprecated_reason=_("Use [ironic]/auth_type, for noauth case " + "set [ironic]/auth_type to `none` and " + "specify ironic API URL via " + "[ironic]/endpoint_override option.")), cfg.StrOpt('ironic_url', default='http://localhost:6385/', help=_('Ironic API URL, used to set Ironic API URL when ' - 'auth_strategy option is noauth to work with standalone ' - 'Ironic without keystone.')), + 'auth_strategy option is noauth or auth_type is "none" ' + 'to work with standalone Ironic without keystone.'), + deprecated_for_removal=True, + deprecated_reason=_('Use [ironic]/endpoint_override option ' + 'to set a specific ironic API url.')), cfg.StrOpt('os_service_type', default='baremetal', - help=_('Ironic service type.')), + help=_('Ironic service type.'), + deprecated_for_removal=True, + deprecated_reason=_('Use [ironic]/service_type option ' + 'to set a specific type.')), cfg.StrOpt('os_endpoint_type', default='internalURL', - help=_('Ironic endpoint type.')), + help=_('Ironic endpoint type.'), + deprecated_for_removal=True, + deprecated_reason=_('Use [ironic]/valid_interfaces option ' + 'to specify endpoint interfaces.')), cfg.IntOpt('retry_interval', default=2, help=_('Interval between retries in case of conflict error ' @@ -52,8 +70,8 @@ _OPTS = [ def register_opts(conf): conf.register_opts(_OPTS, IRONIC_GROUP) - keystone.register_auth_opts(IRONIC_GROUP) + keystone.register_auth_opts(IRONIC_GROUP, SERVICE_TYPE) def list_opts(): - return keystone.add_auth_options(_OPTS) + return keystone.add_auth_options(_OPTS, SERVICE_TYPE) diff --git a/ironic_inspector/conf/swift.py b/ironic_inspector/conf/swift.py index d6c5f66c9..b0429d257 100644 --- a/ironic_inspector/conf/swift.py +++ b/ironic_inspector/conf/swift.py @@ -18,6 +18,7 @@ from ironic_inspector.common import keystone SWIFT_GROUP = 'swift' +SERVICE_TYPE = 'object-store' _OPTS = [ @@ -36,19 +37,28 @@ _OPTS = [ 'objects.')), cfg.StrOpt('os_service_type', default='object-store', - help=_('Swift service type.')), + help=_('Swift service type.'), + deprecated_for_removal=True, + deprecated_reason=_('Use [swift]/service_type option ' + 'to set specific service type')), cfg.StrOpt('os_endpoint_type', default='internalURL', - help=_('Swift endpoint type.')), + help=_('Swift endpoint type.'), + deprecated_for_removal=True, + deprecated_reason=_('Use [swift]/valid_interfaces option ' + 'to specify endpoint interfaces.')), cfg.StrOpt('os_region', - help=_('Keystone region to get endpoint for.')), + help=_('Keystone region to get endpoint for.'), + deprecated_for_removal=True, + deprecated_reason=_("Use [swift]/region_name option to " + "configure region.")) ] def register_opts(conf): conf.register_opts(_OPTS, SWIFT_GROUP) - keystone.register_auth_opts(SWIFT_GROUP) + keystone.register_auth_opts(SWIFT_GROUP, SERVICE_TYPE) def list_opts(): - return keystone.add_auth_options(_OPTS) + return keystone.add_auth_options(_OPTS, SERVICE_TYPE) diff --git a/ironic_inspector/test/functional.py b/ironic_inspector/test/functional.py index 092cb6c08..f30b33cd7 100644 --- a/ironic_inspector/test/functional.py +++ b/ironic_inspector/test/functional.py @@ -49,16 +49,14 @@ from ironic_inspector.test.unit import test_rules CONF = """ [ironic] -os_auth_url = http://url -os_username = user -os_password = password -os_tenant_name = tenant +auth_type=none +endpoint_override=http://url [pxe_filter] driver = noop [DEFAULT] debug = True -auth_strategy = noauth introspection_delay = 0 +auth_strategy=noauth [database] connection = sqlite:///%(db_file)s [processing] diff --git a/ironic_inspector/test/unit/test_common_ironic.py b/ironic_inspector/test/unit/test_common_ironic.py index c9b7ba2ae..8b69a68fd 100644 --- a/ironic_inspector/test/unit/test_common_ironic.py +++ b/ironic_inspector/test/unit/test_common_ironic.py @@ -27,6 +27,7 @@ from ironic_inspector import utils CONF = cfg.CONF +@mock.patch.object(keystone, 'get_adapter') @mock.patch.object(keystone, 'register_auth_opts') @mock.patch.object(keystone, 'get_session') @mock.patch.object(client, 'Client') @@ -39,35 +40,34 @@ class TestGetClient(base.BaseTest): self.addCleanup(ir_utils.reset_ironic_session) def test_get_client_with_auth_token(self, mock_client, mock_load, - mock_opts): + mock_opts, mock_adapter): fake_token = 'token' fake_ironic_url = 'http://127.0.0.1:6385' mock_sess = mock.Mock() - mock_sess.get_endpoint.return_value = fake_ironic_url + mock_adapter.return_value.get_endpoint.return_value = fake_ironic_url mock_load.return_value = mock_sess ir_utils.get_client(fake_token) - mock_sess.get_endpoint.assert_called_once_with( - endpoint_type=CONF.ironic.os_endpoint_type, - service_type=CONF.ironic.os_service_type, - region_name=CONF.ironic.os_region) + mock_adapter.assert_called_once_with( + 'ironic', region_name='somewhere', session=mock_sess) + mock_adapter.return_value.get_endpoint.assert_called_once_with() args = {'token': fake_token, - 'endpoint': fake_ironic_url, 'os_ironic_api_version': ir_utils.DEFAULT_IRONIC_API_VERSION, 'max_retries': CONF.ironic.max_retries, 'retry_interval': CONF.ironic.retry_interval} - mock_client.assert_called_once_with(1, **args) + mock_client.assert_called_once_with(1, fake_ironic_url, **args) def test_get_client_without_auth_token(self, mock_client, mock_load, - mock_opts): + mock_opts, mock_adapter): + fake_ironic_url = 'http://127.0.0.1:6385' + mock_adapter.return_value.get_endpoint.return_value = fake_ironic_url mock_sess = mock.Mock() mock_load.return_value = mock_sess ir_utils.get_client(None) args = {'session': mock_sess, - 'region_name': 'somewhere', 'os_ironic_api_version': ir_utils.DEFAULT_IRONIC_API_VERSION, 'max_retries': CONF.ironic.max_retries, 'retry_interval': CONF.ironic.retry_interval} - mock_client.assert_called_once_with(1, **args) + mock_client.assert_called_once_with(1, fake_ironic_url, **args) class TestGetIpmiAddress(base.BaseTest): diff --git a/ironic_inspector/test/unit/test_keystone.py b/ironic_inspector/test/unit/test_keystone.py index 54f4ba0ca..b1191dadf 100644 --- a/ironic_inspector/test/unit/test_keystone.py +++ b/ironic_inspector/test/unit/test_keystone.py @@ -29,16 +29,18 @@ class KeystoneTest(base.BaseTest): self.cfg.conf.register_group(cfg.OptGroup(TESTGROUP)) def test_register_auth_opts(self): - keystone.register_auth_opts(TESTGROUP) + keystone.register_auth_opts(TESTGROUP, 'fake-service') auth_opts = ['auth_type', 'auth_section'] sess_opts = ['certfile', 'keyfile', 'insecure', 'timeout', 'cafile'] for o in auth_opts + sess_opts: self.assertIn(o, self.cfg.conf[TESTGROUP]) self.assertEqual('password', self.cfg.conf[TESTGROUP]['auth_type']) + self.assertEqual('fake-service', + self.cfg.conf[TESTGROUP]['service_type']) @mock.patch.object(kaloading, 'load_auth_from_conf_options', autospec=True) def test_get_session(self, auth_mock): - keystone.register_auth_opts(TESTGROUP) + keystone.register_auth_opts(TESTGROUP, 'fake-service') self.cfg.config(group=TESTGROUP, cafile='/path/to/ca/file') auth1 = mock.Mock() @@ -48,7 +50,7 @@ class KeystoneTest(base.BaseTest): self.assertEqual(auth1, sess.auth) def test_add_auth_options(self): - opts = keystone.add_auth_options([]) + opts = keystone.add_auth_options([], 'fake-service') # check that there is no duplicates names = {o.dest for o in opts} self.assertEqual(len(names), len(opts)) diff --git a/ironic_inspector/test/unit/test_plugins_rules.py b/ironic_inspector/test/unit/test_plugins_rules.py index d5017e9fd..cfdbbb540 100644 --- a/ironic_inspector/test/unit/test_plugins_rules.py +++ b/ironic_inspector/test/unit/test_plugins_rules.py @@ -166,6 +166,7 @@ class TestSetAttributeAction(test_base.NodeTest): 'value': 42}]) +@mock.patch('ironic_inspector.common.ironic.get_client', new=mock.Mock()) class TestSetCapabilityAction(test_base.NodeTest): act = rules_plugins.SetCapabilityAction() params = {'name': 'cap1', 'value': 'val'} @@ -191,6 +192,7 @@ class TestSetCapabilityAction(test_base.NodeTest): self.assertEqual({'cap1': 'val', 'x': 'y', 'answer': '42'}, new_caps) +@mock.patch('ironic_inspector.common.ironic.get_client', new=mock.Mock()) class TestExtendAttributeAction(test_base.NodeTest): act = rules_plugins.ExtendAttributeAction() params = {'path': '/extra/value', 'value': 42} diff --git a/ironic_inspector/test/unit/test_plugins_standard.py b/ironic_inspector/test/unit/test_plugins_standard.py index d76a84ae7..b1d4a7836 100644 --- a/ironic_inspector/test/unit/test_plugins_standard.py +++ b/ironic_inspector/test/unit/test_plugins_standard.py @@ -26,6 +26,7 @@ from ironic_inspector import utils CONF = cfg.CONF +@mock.patch('ironic_inspector.common.ironic.get_client', new=mock.Mock()) class TestSchedulerHook(test_base.NodeTest): def setUp(self): super(TestSchedulerHook, self).setUp() diff --git a/ironic_inspector/test/unit/test_swift.py b/ironic_inspector/test/unit/test_swift.py index 0491968ea..c32071c76 100644 --- a/ironic_inspector/test/unit/test_swift.py +++ b/ironic_inspector/test/unit/test_swift.py @@ -14,6 +14,8 @@ # Mostly copied from ironic/tests/test_swift.py + +from keystoneauth1 import loading as kloading import mock from swiftclient import client as swift_client from swiftclient import exceptions as swift_exception @@ -44,6 +46,7 @@ class BaseTest(test_base.NodeTest): } +@mock.patch.object(keystone, 'get_adapter', autospec=True) @mock.patch.object(keystone, 'register_auth_opts') @mock.patch.object(keystone, 'get_session') @mock.patch.object(swift_client, 'Connection', autospec=True) @@ -58,14 +61,23 @@ class SwiftTestCase(BaseTest): os_endpoint_type='internalURL', os_region='somewhere', max_retries=2) + # NOTE(aarefiev) register keystoneauth dynamic options + adapter_opts = kloading.get_adapter_conf_options( + include_deprecated=False) + self.cfg.register_opts(adapter_opts, 'swift') self.addCleanup(swift.reset_swift_session) - def test___init__(self, connection_mock, load_mock, opts_mock): + def test___init__(self, connection_mock, load_mock, + opts_mock, adapter_mock): + fake_endpoint = "http://localhost:6000" + adapter_mock.return_value.get_endpoint.return_value = fake_endpoint swift.SwiftAPI() connection_mock.assert_called_once_with( - session=load_mock.return_value) + session=load_mock.return_value, + os_options={'object_storage_url': fake_endpoint}) - def test_create_object(self, connection_mock, load_mock, opts_mock): + def test_create_object(self, connection_mock, load_mock, + opts_mock, adapter_mock): swiftapi = swift.SwiftAPI() connection_obj_mock = connection_mock.return_value @@ -79,8 +91,8 @@ class SwiftTestCase(BaseTest): 'ironic-inspector', 'object', 'some-string-data', headers=None) self.assertEqual('object-uuid', object_uuid) - def test_create_object_create_container_fails(self, connection_mock, - load_mock, opts_mock): + def test_create_object_create_container_fails( + self, connection_mock, load_mock, opts_mock, adapter_mock): swiftapi = swift.SwiftAPI() connection_obj_mock = connection_mock.return_value connection_obj_mock.put_container.side_effect = self.swift_exception @@ -91,7 +103,7 @@ class SwiftTestCase(BaseTest): self.assertFalse(connection_obj_mock.put_object.called) def test_create_object_put_object_fails(self, connection_mock, load_mock, - opts_mock): + opts_mock, adapter_mock): swiftapi = swift.SwiftAPI() connection_obj_mock = connection_mock.return_value connection_obj_mock.put_object.side_effect = self.swift_exception @@ -102,7 +114,8 @@ class SwiftTestCase(BaseTest): connection_obj_mock.put_object.assert_called_once_with( 'ironic-inspector', 'object', 'some-string-data', headers=None) - def test_get_object(self, connection_mock, load_mock, opts_mock): + def test_get_object(self, connection_mock, load_mock, + opts_mock, adapter_mock): swiftapi = swift.SwiftAPI() connection_obj_mock = connection_mock.return_value @@ -115,7 +128,8 @@ class SwiftTestCase(BaseTest): 'ironic-inspector', 'object') self.assertEqual(expected_obj, swift_obj) - def test_get_object_fails(self, connection_mock, load_mock, opts_mock): + def test_get_object_fails(self, connection_mock, load_mock, + opts_mock, adapter_mock): swiftapi = swift.SwiftAPI() connection_obj_mock = connection_mock.return_value connection_obj_mock.get_object.side_effect = self.swift_exception diff --git a/releasenotes/notes/ksadapters-abc9edc63cafa405.yaml b/releasenotes/notes/ksadapters-abc9edc63cafa405.yaml new file mode 100644 index 000000000..8d0cd5461 --- /dev/null +++ b/releasenotes/notes/ksadapters-abc9edc63cafa405.yaml @@ -0,0 +1,24 @@ +--- +deprecations: + - | + Several configuration options related to ironic API access + are deprecated and will be removed in the Rocky release. + These include: + + - ``[ironic]/os_region`` - use ``[ironic]/region_name`` option instead + - ``[ironic]/auth_strategy`` - set ``[ironic]/auth_type`` option to + ``none`` to access ironic API in noauth mode + - ``[ironic]/ironic_url`` - use ``[ironic]/endpoint_override`` option + to set specific ironic API endpoint address if discovery of ironic API + endpoint is not desired or impossible (for example in standalone mode) + - ``[ironic]/os_service_type`` - use ``[ironic]/service_type`` option + - ``[ironic]/os_endpoint_type`` - use ``[ironic]/valid_interfaces`` + option to set ironic endpoint types that will be attempted to be used + - | + Several configuration options related to swift API access are deprecated + and will be removed in Rocky release. + These include: + + - ``[swift]/os_service_type`` - use ``[swift]/service_type`` option + - ``[swift]/os_endpoint_type`` - use ``[swift]/valid_interfaces`` option + - ``[swift]/os_region`` - use ``[swift]region_name`` option