Add a mechanism to call out deprecated options
We have had deprecated command line options in novaclient for a long time, but no warnings about the deprecations were ever emitted, despite the help text being suppressed. It would be nice to finally get rid of those deprecated options. This change sets up the precondition to accomplish this, by emitting appropriate warnings when a deprecated option is used. Note: The "use" text for the deprecated options has been deliberately chosen to reduce the number of translations required. Change-Id: Ibe13faa56c5abca97f85f9c5172ef5a5591b5f71
This commit is contained in:
parent
6d023a6bc2
commit
08c4b746b2
@ -29,6 +29,7 @@ from keystoneauth1 import loading
|
||||
from oslo_utils import encodeutils
|
||||
from oslo_utils import importutils
|
||||
from oslo_utils import strutils
|
||||
import six
|
||||
|
||||
HAS_KEYRING = False
|
||||
all_errors = ValueError
|
||||
@ -63,6 +64,153 @@ HINT_HELP_MSG = (" [hint: use '--os-compute-api-version' flag to show help "
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DeprecatedAction(argparse.Action):
|
||||
"""An argparse action for deprecated options.
|
||||
|
||||
This class is an ``argparse.Action`` subclass that allows command
|
||||
line options to be explicitly deprecated. It modifies the help
|
||||
text for the option to indicate that it's deprecated (unless help
|
||||
has been suppressed using ``argparse.SUPPRESS``), and provides a
|
||||
means to specify an alternate option to use using the ``use``
|
||||
keyword argument to ``argparse.ArgumentParser.add_argument()``.
|
||||
The original action may be specified with the ``real_action``
|
||||
keyword argument, which has the same interpretation as the
|
||||
``action`` argument to ``argparse.ArgumentParser.add_argument()``,
|
||||
with the addition of the special "nothing" action which completely
|
||||
ignores the option (other than emitting the deprecation warning).
|
||||
Note that the deprecation warning is only emitted once per
|
||||
specific option string.
|
||||
|
||||
Note: If the ``real_action`` keyword argument specifies an unknown
|
||||
action, no warning will be emitted unless the action is used, due
|
||||
to limitations with the method used to resolve the action names.
|
||||
"""
|
||||
|
||||
def __init__(self, option_strings, dest, help=None,
|
||||
real_action=None, use=None, **kwargs):
|
||||
"""Initialize a ``DeprecatedAction`` instance.
|
||||
|
||||
:param option_strings: The recognized option strings.
|
||||
:param dest: The attribute that will be set.
|
||||
:param help: Help text. This will be updated to indicate the
|
||||
deprecation, and if ``use`` is provided, that
|
||||
text will be included as well.
|
||||
:param real_action: The actual action to invoke. This is
|
||||
interpreted the same way as the ``action``
|
||||
parameter.
|
||||
:param use: Text explaining which option to use instead.
|
||||
"""
|
||||
|
||||
# Update the help text
|
||||
if not help:
|
||||
if use:
|
||||
help = _('Deprecated; %(use)s') % {'use': use}
|
||||
else:
|
||||
help = _('Deprecated')
|
||||
elif help != argparse.SUPPRESS:
|
||||
if use:
|
||||
help = _('%(help)s (Deprecated; %(use)s)') % {
|
||||
'help': help,
|
||||
'use': use,
|
||||
}
|
||||
else:
|
||||
help = _('%(help)s (Deprecated)') % {'help': help}
|
||||
|
||||
# Initialize ourself appropriately
|
||||
super(DeprecatedAction, self).__init__(
|
||||
option_strings, dest, help=help, **kwargs)
|
||||
|
||||
# 'emitted' tracks which warnings we've emitted
|
||||
self.emitted = set()
|
||||
self.use = use
|
||||
|
||||
# Select the appropriate action
|
||||
if real_action == 'nothing':
|
||||
# NOTE(Vek): "nothing" is distinct from a real_action=None
|
||||
# argument. When real_action=None, the argparse default
|
||||
# action of "store" is used; when real_action='nothing',
|
||||
# however, we explicitly inhibit doing anything with the
|
||||
# option
|
||||
self.real_action_args = False
|
||||
self.real_action = None
|
||||
elif real_action is None or isinstance(real_action, six.string_types):
|
||||
# Specified by string (or None); we have to have a parser
|
||||
# to look up the actual action, so defer to later
|
||||
self.real_action_args = (option_strings, dest, help, kwargs)
|
||||
self.real_action = real_action
|
||||
else:
|
||||
self.real_action_args = False
|
||||
self.real_action = real_action(
|
||||
option_strings, dest, help=help, **kwargs)
|
||||
|
||||
def _get_action(self, parser):
|
||||
"""Retrieve the action callable.
|
||||
|
||||
This internal method is used to retrieve the callable
|
||||
implementing the action. If ``real_action`` was specified as
|
||||
``None`` or one of the standard string names, an internal
|
||||
method of the ``argparse.ArgumentParser`` instance is used to
|
||||
resolve it into an actual action class, which is then
|
||||
instantiated. This is cached, in case the action is called
|
||||
multiple times.
|
||||
|
||||
:param parser: The ``argparse.ArgumentParser`` instance.
|
||||
|
||||
:returns: The action callable.
|
||||
"""
|
||||
|
||||
# If a lookup is needed, look up the action in the parser
|
||||
if self.real_action_args is not False:
|
||||
option_strings, dest, help, kwargs = self.real_action_args
|
||||
action_class = parser._registry_get('action', self.real_action)
|
||||
|
||||
# Did we find the action class?
|
||||
if action_class is None:
|
||||
print(_('WARNING: Programming error: Unknown real action '
|
||||
'"%s"') % self.real_action, file=sys.stderr)
|
||||
self.real_action = None
|
||||
else:
|
||||
# OK, instantiate the action class
|
||||
self.real_action = action_class(
|
||||
option_strings, dest, help=help, **kwargs)
|
||||
|
||||
# It's been resolved, no further need to look it up
|
||||
self.real_action_args = False
|
||||
|
||||
return self.real_action
|
||||
|
||||
def __call__(self, parser, namespace, values, option_string):
|
||||
"""Implement the action.
|
||||
|
||||
Emits the deprecation warning message (only once for any given
|
||||
option string), then calls the real action (if any).
|
||||
|
||||
:param parser: The ``argparse.ArgumentParser`` instance.
|
||||
:param namespace: The ``argparse.Namespace`` object which
|
||||
should have an attribute set.
|
||||
:param values: Any arguments provided to the option.
|
||||
:param option_string: The option string that was used.
|
||||
"""
|
||||
|
||||
action = self._get_action(parser)
|
||||
|
||||
# Only emit the deprecation warning once per option
|
||||
if option_string not in self.emitted:
|
||||
if self.use:
|
||||
print(_('WARNING: Option "%(option)s" is deprecated; '
|
||||
'%(use)s') % {
|
||||
'option': option_string,
|
||||
'use': self.use,
|
||||
}, file=sys.stderr)
|
||||
else:
|
||||
print(_('WARNING: Option "%(option)s" is deprecated') %
|
||||
{'option': option_string}, file=sys.stderr)
|
||||
self.emitted.add(option_string)
|
||||
|
||||
if action:
|
||||
action(parser, namespace, values, option_string)
|
||||
|
||||
|
||||
def positive_non_zero_float(text):
|
||||
if text is None:
|
||||
return None
|
||||
@ -313,24 +461,32 @@ class OpenStackComputeShell(object):
|
||||
action='store_true',
|
||||
help=_("Print call timing info."))
|
||||
|
||||
parser.add_argument(
|
||||
'--os-auth-token',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument(
|
||||
'--os_username',
|
||||
action=DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed '
|
||||
'in novaclient 3.3.0.') % '--os-username',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument(
|
||||
'--os_password',
|
||||
action=DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed '
|
||||
'in novaclient 3.3.0.') % '--os-password',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument(
|
||||
'--os_tenant_name',
|
||||
action=DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed '
|
||||
'in novaclient 3.3.0.') % '--os-tenant-name',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument(
|
||||
'--os_auth_url',
|
||||
action=DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed '
|
||||
'in novaclient 3.3.0.') % '--os-auth-url',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument(
|
||||
@ -340,6 +496,9 @@ class OpenStackComputeShell(object):
|
||||
help=_('Defaults to env[OS_REGION_NAME].'))
|
||||
parser.add_argument(
|
||||
'--os_region_name',
|
||||
action=DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed '
|
||||
'in novaclient 3.3.0.') % '--os-region-name',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument(
|
||||
@ -349,6 +508,9 @@ class OpenStackComputeShell(object):
|
||||
help=argparse.SUPPRESS)
|
||||
parser.add_argument(
|
||||
'--os_auth_system',
|
||||
action=DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed '
|
||||
'in novaclient 3.3.0.') % '--os-auth-system',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument(
|
||||
@ -357,6 +519,9 @@ class OpenStackComputeShell(object):
|
||||
help=_('Defaults to compute for most actions.'))
|
||||
parser.add_argument(
|
||||
'--service_type',
|
||||
action=DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed '
|
||||
'in novaclient 3.3.0.') % '--service-type',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument(
|
||||
@ -366,6 +531,9 @@ class OpenStackComputeShell(object):
|
||||
help=_('Defaults to env[NOVA_SERVICE_NAME].'))
|
||||
parser.add_argument(
|
||||
'--service_name',
|
||||
action=DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed '
|
||||
'in novaclient 3.3.0.') % '--service-name',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument(
|
||||
@ -375,6 +543,9 @@ class OpenStackComputeShell(object):
|
||||
help=_('Defaults to env[NOVA_VOLUME_SERVICE_NAME].'))
|
||||
parser.add_argument(
|
||||
'--volume_service_name',
|
||||
action=DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed '
|
||||
'in novaclient 3.3.0.') % '--volume-service-name',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument(
|
||||
@ -391,6 +562,9 @@ class OpenStackComputeShell(object):
|
||||
|
||||
parser.add_argument(
|
||||
'--endpoint-type',
|
||||
action=DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed '
|
||||
'in novaclient 3.3.0.') % '--os-endpoint-type',
|
||||
help=argparse.SUPPRESS)
|
||||
# NOTE(dtroyer): We can't add --endpoint_type here due to argparse
|
||||
# thinking usage-list --end is ambiguous; but it
|
||||
@ -408,6 +582,9 @@ class OpenStackComputeShell(object):
|
||||
'"X.latest", defaults to env[OS_COMPUTE_API_VERSION].'))
|
||||
parser.add_argument(
|
||||
'--os_compute_api_version',
|
||||
action=DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed '
|
||||
'in novaclient 3.3.0.') % '--os-compute-api-version',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument(
|
||||
@ -417,8 +594,12 @@ class OpenStackComputeShell(object):
|
||||
default=utils.env('NOVACLIENT_BYPASS_URL'),
|
||||
help="Use this API endpoint instead of the Service Catalog. "
|
||||
"Defaults to env[NOVACLIENT_BYPASS_URL].")
|
||||
parser.add_argument('--bypass_url',
|
||||
help=argparse.SUPPRESS)
|
||||
parser.add_argument(
|
||||
'--bypass_url',
|
||||
action=DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed '
|
||||
'in novaclient 3.3.0.') % '--bypass-url',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
# The auth-system-plugins might require some extra options
|
||||
novaclient.auth_plugin.load_auth_system_opts(parser)
|
||||
@ -544,10 +725,18 @@ class OpenStackComputeShell(object):
|
||||
if '--endpoint_type' in argv:
|
||||
spot = argv.index('--endpoint_type')
|
||||
argv[spot] = '--endpoint-type'
|
||||
# NOTE(Vek): Not emitting a warning here, as that will
|
||||
# occur when "--endpoint-type" is processed
|
||||
|
||||
# For backwards compat with old os-auth-token parameter
|
||||
if '--os-auth-token' in argv:
|
||||
spot = argv.index('--os-auth-token')
|
||||
argv[spot] = '--os-token'
|
||||
print(_('WARNING: Option "%(option)s" is deprecated; %(use)s') % {
|
||||
'option': '--os-auth-token',
|
||||
'use': _('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--os-token',
|
||||
}, file=sys.stderr)
|
||||
|
||||
(args, args_list) = parser.parse_known_args(argv)
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import argparse
|
||||
import distutils.version as dist_version
|
||||
import re
|
||||
import sys
|
||||
@ -76,6 +77,261 @@ def _create_ver_list(versions):
|
||||
return {'versions': {'values': versions}}
|
||||
|
||||
|
||||
class DeprecatedActionTest(utils.TestCase):
|
||||
@mock.patch.object(argparse.Action, '__init__', return_value=None)
|
||||
def test_init_emptyhelp_nouse(self, mock_init):
|
||||
result = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest', a=1, b=2, c=3)
|
||||
|
||||
self.assertEqual(result.emitted, set())
|
||||
self.assertEqual(result.use, None)
|
||||
self.assertEqual(result.real_action_args,
|
||||
('option_strings', 'dest', 'Deprecated',
|
||||
{'a': 1, 'b': 2, 'c': 3}))
|
||||
self.assertEqual(result.real_action, None)
|
||||
mock_init.assert_called_once_with(
|
||||
'option_strings', 'dest', help='Deprecated', a=1, b=2, c=3)
|
||||
|
||||
@mock.patch.object(novaclient.shell.argparse.Action, '__init__',
|
||||
return_value=None)
|
||||
def test_init_emptyhelp_withuse(self, mock_init):
|
||||
result = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest', use='use this instead', a=1, b=2, c=3)
|
||||
|
||||
self.assertEqual(result.emitted, set())
|
||||
self.assertEqual(result.use, 'use this instead')
|
||||
self.assertEqual(result.real_action_args,
|
||||
('option_strings', 'dest',
|
||||
'Deprecated; use this instead',
|
||||
{'a': 1, 'b': 2, 'c': 3}))
|
||||
self.assertEqual(result.real_action, None)
|
||||
mock_init.assert_called_once_with(
|
||||
'option_strings', 'dest', help='Deprecated; use this instead',
|
||||
a=1, b=2, c=3)
|
||||
|
||||
@mock.patch.object(argparse.Action, '__init__', return_value=None)
|
||||
def test_init_withhelp_nouse(self, mock_init):
|
||||
result = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest', help='some help', a=1, b=2, c=3)
|
||||
|
||||
self.assertEqual(result.emitted, set())
|
||||
self.assertEqual(result.use, None)
|
||||
self.assertEqual(result.real_action_args,
|
||||
('option_strings', 'dest',
|
||||
'some help (Deprecated)',
|
||||
{'a': 1, 'b': 2, 'c': 3}))
|
||||
self.assertEqual(result.real_action, None)
|
||||
mock_init.assert_called_once_with(
|
||||
'option_strings', 'dest', help='some help (Deprecated)',
|
||||
a=1, b=2, c=3)
|
||||
|
||||
@mock.patch.object(novaclient.shell.argparse.Action, '__init__',
|
||||
return_value=None)
|
||||
def test_init_withhelp_withuse(self, mock_init):
|
||||
result = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest', help='some help',
|
||||
use='use this instead', a=1, b=2, c=3)
|
||||
|
||||
self.assertEqual(result.emitted, set())
|
||||
self.assertEqual(result.use, 'use this instead')
|
||||
self.assertEqual(result.real_action_args,
|
||||
('option_strings', 'dest',
|
||||
'some help (Deprecated; use this instead)',
|
||||
{'a': 1, 'b': 2, 'c': 3}))
|
||||
self.assertEqual(result.real_action, None)
|
||||
mock_init.assert_called_once_with(
|
||||
'option_strings', 'dest',
|
||||
help='some help (Deprecated; use this instead)',
|
||||
a=1, b=2, c=3)
|
||||
|
||||
@mock.patch.object(argparse.Action, '__init__', return_value=None)
|
||||
def test_init_suppresshelp_nouse(self, mock_init):
|
||||
result = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest', help=argparse.SUPPRESS, a=1, b=2, c=3)
|
||||
|
||||
self.assertEqual(result.emitted, set())
|
||||
self.assertEqual(result.use, None)
|
||||
self.assertEqual(result.real_action_args,
|
||||
('option_strings', 'dest', argparse.SUPPRESS,
|
||||
{'a': 1, 'b': 2, 'c': 3}))
|
||||
self.assertEqual(result.real_action, None)
|
||||
mock_init.assert_called_once_with(
|
||||
'option_strings', 'dest', help=argparse.SUPPRESS, a=1, b=2, c=3)
|
||||
|
||||
@mock.patch.object(novaclient.shell.argparse.Action, '__init__',
|
||||
return_value=None)
|
||||
def test_init_suppresshelp_withuse(self, mock_init):
|
||||
result = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest', help=argparse.SUPPRESS,
|
||||
use='use this instead', a=1, b=2, c=3)
|
||||
|
||||
self.assertEqual(result.emitted, set())
|
||||
self.assertEqual(result.use, 'use this instead')
|
||||
self.assertEqual(result.real_action_args,
|
||||
('option_strings', 'dest', argparse.SUPPRESS,
|
||||
{'a': 1, 'b': 2, 'c': 3}))
|
||||
self.assertEqual(result.real_action, None)
|
||||
mock_init.assert_called_once_with(
|
||||
'option_strings', 'dest', help=argparse.SUPPRESS, a=1, b=2, c=3)
|
||||
|
||||
@mock.patch.object(argparse.Action, '__init__', return_value=None)
|
||||
def test_init_action_nothing(self, mock_init):
|
||||
result = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest', real_action='nothing', a=1, b=2, c=3)
|
||||
|
||||
self.assertEqual(result.emitted, set())
|
||||
self.assertEqual(result.use, None)
|
||||
self.assertEqual(result.real_action_args, False)
|
||||
self.assertEqual(result.real_action, None)
|
||||
mock_init.assert_called_once_with(
|
||||
'option_strings', 'dest', help='Deprecated', a=1, b=2, c=3)
|
||||
|
||||
@mock.patch.object(argparse.Action, '__init__', return_value=None)
|
||||
def test_init_action_string(self, mock_init):
|
||||
result = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest', real_action='store', a=1, b=2, c=3)
|
||||
|
||||
self.assertEqual(result.emitted, set())
|
||||
self.assertEqual(result.use, None)
|
||||
self.assertEqual(result.real_action_args,
|
||||
('option_strings', 'dest', 'Deprecated',
|
||||
{'a': 1, 'b': 2, 'c': 3}))
|
||||
self.assertEqual(result.real_action, 'store')
|
||||
mock_init.assert_called_once_with(
|
||||
'option_strings', 'dest', help='Deprecated', a=1, b=2, c=3)
|
||||
|
||||
@mock.patch.object(argparse.Action, '__init__', return_value=None)
|
||||
def test_init_action_other(self, mock_init):
|
||||
action = mock.Mock()
|
||||
result = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest', real_action=action, a=1, b=2, c=3)
|
||||
|
||||
self.assertEqual(result.emitted, set())
|
||||
self.assertEqual(result.use, None)
|
||||
self.assertEqual(result.real_action_args, False)
|
||||
self.assertEqual(result.real_action, action.return_value)
|
||||
mock_init.assert_called_once_with(
|
||||
'option_strings', 'dest', help='Deprecated', a=1, b=2, c=3)
|
||||
action.assert_called_once_with(
|
||||
'option_strings', 'dest', help='Deprecated', a=1, b=2, c=3)
|
||||
|
||||
@mock.patch.object(sys, 'stderr', six.StringIO())
|
||||
def test_get_action_nolookup(self):
|
||||
action_class = mock.Mock()
|
||||
parser = mock.Mock(**{
|
||||
'_registry_get.return_value': action_class,
|
||||
})
|
||||
obj = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest', real_action='nothing', const=1)
|
||||
obj.real_action = 'action'
|
||||
|
||||
result = obj._get_action(parser)
|
||||
|
||||
self.assertEqual(result, 'action')
|
||||
self.assertEqual(obj.real_action, 'action')
|
||||
self.assertFalse(parser._registry_get.called)
|
||||
self.assertFalse(action_class.called)
|
||||
self.assertEqual(sys.stderr.getvalue(), '')
|
||||
|
||||
@mock.patch.object(sys, 'stderr', six.StringIO())
|
||||
def test_get_action_lookup_noresult(self):
|
||||
parser = mock.Mock(**{
|
||||
'_registry_get.return_value': None,
|
||||
})
|
||||
obj = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest', real_action='store', const=1)
|
||||
|
||||
result = obj._get_action(parser)
|
||||
|
||||
self.assertEqual(result, None)
|
||||
self.assertEqual(obj.real_action, None)
|
||||
parser._registry_get.assert_called_once_with(
|
||||
'action', 'store')
|
||||
self.assertEqual(sys.stderr.getvalue(),
|
||||
'WARNING: Programming error: Unknown real action '
|
||||
'"store"\n')
|
||||
|
||||
@mock.patch.object(sys, 'stderr', six.StringIO())
|
||||
def test_get_action_lookup_withresult(self):
|
||||
action_class = mock.Mock()
|
||||
parser = mock.Mock(**{
|
||||
'_registry_get.return_value': action_class,
|
||||
})
|
||||
obj = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest', real_action='store', const=1)
|
||||
|
||||
result = obj._get_action(parser)
|
||||
|
||||
self.assertEqual(result, action_class.return_value)
|
||||
self.assertEqual(obj.real_action, action_class.return_value)
|
||||
parser._registry_get.assert_called_once_with(
|
||||
'action', 'store')
|
||||
action_class.assert_called_once_with(
|
||||
'option_strings', 'dest', help='Deprecated', const=1)
|
||||
self.assertEqual(sys.stderr.getvalue(), '')
|
||||
|
||||
@mock.patch.object(sys, 'stderr', six.StringIO())
|
||||
@mock.patch.object(novaclient.shell.DeprecatedAction, '_get_action')
|
||||
def test_call_unemitted_nouse(self, mock_get_action):
|
||||
obj = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest')
|
||||
|
||||
obj('parser', 'namespace', 'values', 'option_string')
|
||||
|
||||
self.assertEqual(obj.emitted, set(['option_string']))
|
||||
mock_get_action.assert_called_once_with('parser')
|
||||
mock_get_action.return_value.assert_called_once_with(
|
||||
'parser', 'namespace', 'values', 'option_string')
|
||||
self.assertEqual(sys.stderr.getvalue(),
|
||||
'WARNING: Option "option_string" is deprecated\n')
|
||||
|
||||
@mock.patch.object(sys, 'stderr', six.StringIO())
|
||||
@mock.patch.object(novaclient.shell.DeprecatedAction, '_get_action')
|
||||
def test_call_unemitted_withuse(self, mock_get_action):
|
||||
obj = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest', use='use this instead')
|
||||
|
||||
obj('parser', 'namespace', 'values', 'option_string')
|
||||
|
||||
self.assertEqual(obj.emitted, set(['option_string']))
|
||||
mock_get_action.assert_called_once_with('parser')
|
||||
mock_get_action.return_value.assert_called_once_with(
|
||||
'parser', 'namespace', 'values', 'option_string')
|
||||
self.assertEqual(sys.stderr.getvalue(),
|
||||
'WARNING: Option "option_string" is deprecated; '
|
||||
'use this instead\n')
|
||||
|
||||
@mock.patch.object(sys, 'stderr', six.StringIO())
|
||||
@mock.patch.object(novaclient.shell.DeprecatedAction, '_get_action')
|
||||
def test_call_emitted_nouse(self, mock_get_action):
|
||||
obj = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest')
|
||||
obj.emitted.add('option_string')
|
||||
|
||||
obj('parser', 'namespace', 'values', 'option_string')
|
||||
|
||||
self.assertEqual(obj.emitted, set(['option_string']))
|
||||
mock_get_action.assert_called_once_with('parser')
|
||||
mock_get_action.return_value.assert_called_once_with(
|
||||
'parser', 'namespace', 'values', 'option_string')
|
||||
self.assertEqual(sys.stderr.getvalue(), '')
|
||||
|
||||
@mock.patch.object(sys, 'stderr', six.StringIO())
|
||||
@mock.patch.object(novaclient.shell.DeprecatedAction, '_get_action')
|
||||
def test_call_emitted_withuse(self, mock_get_action):
|
||||
obj = novaclient.shell.DeprecatedAction(
|
||||
'option_strings', 'dest', use='use this instead')
|
||||
obj.emitted.add('option_string')
|
||||
|
||||
obj('parser', 'namespace', 'values', 'option_string')
|
||||
|
||||
self.assertEqual(obj.emitted, set(['option_string']))
|
||||
mock_get_action.assert_called_once_with('parser')
|
||||
mock_get_action.return_value.assert_called_once_with(
|
||||
'parser', 'namespace', 'values', 'option_string')
|
||||
self.assertEqual(sys.stderr.getvalue(), '')
|
||||
|
||||
|
||||
class ParserTest(utils.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -43,6 +43,7 @@ from novaclient import client
|
||||
from novaclient import exceptions
|
||||
from novaclient.i18n import _
|
||||
from novaclient.openstack.common import cliutils
|
||||
from novaclient import shell
|
||||
from novaclient import utils
|
||||
from novaclient.v2 import availability_zones
|
||||
from novaclient.v2 import quotas
|
||||
@ -376,6 +377,9 @@ def _boot(cs, args):
|
||||
default=None,
|
||||
type=int,
|
||||
metavar='<number>',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "--min-count" and "--max-count"; this option will be removed '
|
||||
'in novaclient 3.3.0.'),
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--min-count',
|
||||
@ -412,6 +416,9 @@ def _boot(cs, args):
|
||||
the command keypair-add."))
|
||||
@cliutils.arg(
|
||||
'--key_name',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--key-name',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg('name', metavar='<name>', help=_('Name for the new server.'))
|
||||
@cliutils.arg(
|
||||
@ -421,6 +428,9 @@ def _boot(cs, args):
|
||||
help=_("user data file to pass to be exposed by the metadata server."))
|
||||
@cliutils.arg(
|
||||
'--user_data',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--user-data',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--availability-zone',
|
||||
@ -429,6 +439,9 @@ def _boot(cs, args):
|
||||
help=_("The availability zone for server placement."))
|
||||
@cliutils.arg(
|
||||
'--availability_zone',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--availability-zone',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--security-groups',
|
||||
@ -437,6 +450,9 @@ def _boot(cs, args):
|
||||
help=_("Comma separated list of security group names."))
|
||||
@cliutils.arg(
|
||||
'--security_groups',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--security-groups',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--block-device-mapping',
|
||||
@ -447,7 +463,10 @@ def _boot(cs, args):
|
||||
"<dev-name>=<id>:<type>:<size(GB)>:<delete-on-terminate>."))
|
||||
@cliutils.arg(
|
||||
'--block_device_mapping',
|
||||
action='append',
|
||||
real_action='append',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--block-device-mapping',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--block-device',
|
||||
@ -1288,6 +1307,9 @@ def do_image_delete(cs, args):
|
||||
help=_('Only return servers that match reservation-id.'))
|
||||
@cliutils.arg(
|
||||
'--reservation_id',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--reservation-id',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--ip',
|
||||
@ -1315,6 +1337,9 @@ def do_image_delete(cs, args):
|
||||
help=_('Search with regular expression match by server name.'))
|
||||
@cliutils.arg(
|
||||
'--instance_name',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--instance-name',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--status',
|
||||
@ -1356,6 +1381,9 @@ def do_image_delete(cs, args):
|
||||
nargs='?',
|
||||
type=int,
|
||||
const=1,
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--all-tenants',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--tenant',
|
||||
@ -1561,6 +1589,9 @@ def do_reboot(cs, args):
|
||||
help=_("Set the provided admin password on the rebuilt server."))
|
||||
@cliutils.arg(
|
||||
'--rebuild_password',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--rebuild-password',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--poll',
|
||||
@ -2132,6 +2163,9 @@ def _translate_volume_attachments_keys(collection):
|
||||
nargs='?',
|
||||
type=int,
|
||||
const=1,
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--all-tenants',
|
||||
help=argparse.SUPPRESS)
|
||||
def do_volume_list(cs, args):
|
||||
"""DEPRECATED: List all the volumes."""
|
||||
@ -2171,6 +2205,9 @@ def do_volume_show(cs, args):
|
||||
help=_('Optional snapshot ID to create the volume from. (Default=None)'))
|
||||
@cliutils.arg(
|
||||
'--snapshot_id',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--snapshot-id',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--image-id',
|
||||
@ -2184,6 +2221,9 @@ def do_volume_show(cs, args):
|
||||
help=_('Optional volume name. (Default=None)'))
|
||||
@cliutils.arg(
|
||||
'--display_name',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--display-name',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--display-description',
|
||||
@ -2192,6 +2232,9 @@ def do_volume_show(cs, args):
|
||||
help=_('Optional volume description. (Default=None)'))
|
||||
@cliutils.arg(
|
||||
'--display_description',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--display-description',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--volume-type',
|
||||
@ -2200,6 +2243,9 @@ def do_volume_show(cs, args):
|
||||
help=_('Optional volume type. (Default=None)'))
|
||||
@cliutils.arg(
|
||||
'--volume_type',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--volume-type',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--availability-zone', metavar='<availability-zone>',
|
||||
@ -2338,6 +2384,9 @@ def do_volume_snapshot_show(cs, args):
|
||||
help=_('Optional snapshot name. (Default=None)'))
|
||||
@cliutils.arg(
|
||||
'--display_name',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--display-name',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--display-description',
|
||||
@ -2346,6 +2395,9 @@ def do_volume_snapshot_show(cs, args):
|
||||
help=_('Optional snapshot description. (Default=None)'))
|
||||
@cliutils.arg(
|
||||
'--display_description',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--display-description',
|
||||
help=argparse.SUPPRESS)
|
||||
def do_volume_snapshot_create(cs, args):
|
||||
"""DEPRECATED: Add a new snapshot."""
|
||||
@ -2462,8 +2514,16 @@ def do_get_rdp_console(cs, args):
|
||||
|
||||
@cliutils.arg('server', metavar='<server>', help=_('Name or ID of server.'))
|
||||
@cliutils.arg(
|
||||
'--console_type', default='serial',
|
||||
'--console-type',
|
||||
default='serial',
|
||||
help=_('Type of serial console, default="serial".'))
|
||||
@cliutils.arg(
|
||||
'--console_type',
|
||||
default='serial',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--console-type',
|
||||
help=argparse.SUPPRESS)
|
||||
def do_get_serial_console(cs, args):
|
||||
"""Get a serial console to a server."""
|
||||
if args.console_type not in ('serial',):
|
||||
@ -2741,6 +2801,9 @@ def do_dns_delete_domain(cs, args):
|
||||
'in the specified availability zone.'))
|
||||
@cliutils.arg(
|
||||
'--availability_zone',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--availability-zone',
|
||||
help=argparse.SUPPRESS)
|
||||
def do_dns_create_private_domain(cs, args):
|
||||
"""Create the specified DNS domain."""
|
||||
@ -2925,6 +2988,9 @@ def do_secgroup_delete(cs, args):
|
||||
nargs='?',
|
||||
type=int,
|
||||
const=1,
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--all-tenants',
|
||||
help=argparse.SUPPRESS)
|
||||
def do_secgroup_list(cs, args):
|
||||
"""List security groups for the current tenant."""
|
||||
@ -3054,6 +3120,9 @@ def _keypair_create(cs, args, name, pub_key):
|
||||
help=_('Path to a public ssh key.'))
|
||||
@cliutils.arg(
|
||||
'--pub_key',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--pub-key',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--key-type',
|
||||
@ -3666,7 +3735,10 @@ def _print_aggregate_details(aggregate):
|
||||
help=_('True in case of block_migration. (Default=False:live_migration)'))
|
||||
@cliutils.arg(
|
||||
'--block_migrate',
|
||||
action='store_true',
|
||||
real_action='store_true',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--block-migrate',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--disk-over-commit',
|
||||
@ -3676,7 +3748,10 @@ def _print_aggregate_details(aggregate):
|
||||
help=_('Allow overcommit. (Default=False)'))
|
||||
@cliutils.arg(
|
||||
'--disk_over_commit',
|
||||
action='store_true',
|
||||
real_action='store_true',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--disk-over-commit',
|
||||
help=argparse.SUPPRESS)
|
||||
def do_live_migration(cs, args):
|
||||
"""Migrate running server to a new machine."""
|
||||
@ -4276,6 +4351,9 @@ def do_quota_defaults(cs, args):
|
||||
@cliutils.arg(
|
||||
'--floating_ips',
|
||||
type=int,
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--floating-ips',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--fixed-ips',
|
||||
@ -4292,6 +4370,9 @@ def do_quota_defaults(cs, args):
|
||||
@cliutils.arg(
|
||||
'--metadata_items',
|
||||
type=int,
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--metadata-items',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--injected-files',
|
||||
@ -4302,6 +4383,9 @@ def do_quota_defaults(cs, args):
|
||||
@cliutils.arg(
|
||||
'--injected_files',
|
||||
type=int,
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--injected-files',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--injected-file-content-bytes',
|
||||
@ -4312,6 +4396,9 @@ def do_quota_defaults(cs, args):
|
||||
@cliutils.arg(
|
||||
'--injected_file_content_bytes',
|
||||
type=int,
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--injected-file-content-bytes',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--injected-file-path-bytes',
|
||||
@ -4417,6 +4504,9 @@ def do_quota_class_show(cs, args):
|
||||
@cliutils.arg(
|
||||
'--floating_ips',
|
||||
type=int,
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--floating-ips',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--fixed-ips',
|
||||
@ -4433,6 +4523,9 @@ def do_quota_class_show(cs, args):
|
||||
@cliutils.arg(
|
||||
'--metadata_items',
|
||||
type=int,
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--metadata-items',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--injected-files',
|
||||
@ -4443,6 +4536,9 @@ def do_quota_class_show(cs, args):
|
||||
@cliutils.arg(
|
||||
'--injected_files',
|
||||
type=int,
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--injected-files',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--injected-file-content-bytes',
|
||||
@ -4453,6 +4549,9 @@ def do_quota_class_show(cs, args):
|
||||
@cliutils.arg(
|
||||
'--injected_file_content_bytes',
|
||||
type=int,
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use "%s"; this option will be removed in '
|
||||
'novaclient 3.3.0.') % '--injected-file-content-bytes',
|
||||
help=argparse.SUPPRESS)
|
||||
@cliutils.arg(
|
||||
'--injected-file-path-bytes',
|
||||
@ -4744,7 +4843,10 @@ def do_secgroup_delete_default_rule(cs, args):
|
||||
@cliutils.arg(
|
||||
'--policy',
|
||||
default=[],
|
||||
action='append',
|
||||
real_action='append',
|
||||
action=shell.DeprecatedAction,
|
||||
use=_('use positional parameters; this option will be removed in '
|
||||
'novaclient 3.3.0.'),
|
||||
help=argparse.SUPPRESS)
|
||||
def do_server_group_create(cs, args):
|
||||
"""Create a new server group with the specified details."""
|
||||
|
Loading…
x
Reference in New Issue
Block a user