Merge "Log warning when API version is not specified for the ironic tool"
This commit is contained in:
@@ -39,6 +39,13 @@ from ironicclient import exc
|
|||||||
|
|
||||||
|
|
||||||
LATEST_API_VERSION = ('1', 'latest')
|
LATEST_API_VERSION = ('1', 'latest')
|
||||||
|
MISSING_VERSION_WARNING = (
|
||||||
|
"You are using the default API version of the 'ironic' command "
|
||||||
|
"This is currently API version %s. In the future, the default will be "
|
||||||
|
"the latest API version understood by both API and CLI. You can preserve "
|
||||||
|
"the current behavior by passing the --ironic-api-version argument with "
|
||||||
|
"the desired version or using the IRONIC_API_VERSION environment variable."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class IronicShell(object):
|
class IronicShell(object):
|
||||||
@@ -153,8 +160,8 @@ class IronicShell(object):
|
|||||||
help=argparse.SUPPRESS)
|
help=argparse.SUPPRESS)
|
||||||
|
|
||||||
parser.add_argument('--ironic-api-version',
|
parser.add_argument('--ironic-api-version',
|
||||||
default=cliutils.env(
|
default=cliutils.env('IRONIC_API_VERSION',
|
||||||
'IRONIC_API_VERSION', default='1'),
|
default=None),
|
||||||
help=_('Accepts 1.x (where "x" is microversion) '
|
help=_('Accepts 1.x (where "x" is microversion) '
|
||||||
'or "latest", Defaults to '
|
'or "latest", Defaults to '
|
||||||
'env[IRONIC_API_VERSION] or 1'))
|
'env[IRONIC_API_VERSION] or 1'))
|
||||||
@@ -294,6 +301,11 @@ class IronicShell(object):
|
|||||||
if api_version == 'latest':
|
if api_version == 'latest':
|
||||||
return LATEST_API_VERSION
|
return LATEST_API_VERSION
|
||||||
else:
|
else:
|
||||||
|
if api_version is None:
|
||||||
|
print(MISSING_VERSION_WARNING % http.DEFAULT_VER,
|
||||||
|
file=sys.stderr)
|
||||||
|
api_version = '1'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
versions = tuple(int(i) for i in api_version.split('.'))
|
versions = tuple(int(i) for i in api_version.split('.'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@@ -126,7 +126,7 @@ class FunctionalTestBase(base.ClientTestBase):
|
|||||||
return base.execute(cmd, action, flags, params,
|
return base.execute(cmd, action, flags, params,
|
||||||
cli_dir=self.client.cli_dir)
|
cli_dir=self.client.cli_dir)
|
||||||
|
|
||||||
def _ironic(self, action, flags='', params=''):
|
def _ironic(self, action, flags='', params='', merge_stderr=False):
|
||||||
"""Execute ironic command for the given action.
|
"""Execute ironic command for the given action.
|
||||||
|
|
||||||
:param action: the cli command to run using Ironic
|
:param action: the cli command to run using Ironic
|
||||||
@@ -135,6 +135,8 @@ class FunctionalTestBase(base.ClientTestBase):
|
|||||||
:type flags: string
|
:type flags: string
|
||||||
:param params: any optional positional args to use
|
:param params: any optional positional args to use
|
||||||
:type params: string
|
:type params: string
|
||||||
|
:param merge_stderr: whether to merge stderr into the result
|
||||||
|
:type merge_stderr: bool
|
||||||
"""
|
"""
|
||||||
flags += ' --os-endpoint-type publicURL'
|
flags += ' --os-endpoint-type publicURL'
|
||||||
if hasattr(self, 'os_auth_token'):
|
if hasattr(self, 'os_auth_token'):
|
||||||
@@ -148,7 +150,8 @@ class FunctionalTestBase(base.ClientTestBase):
|
|||||||
'value': getattr(self, domain_attr)
|
'value': getattr(self, domain_attr)
|
||||||
}
|
}
|
||||||
return self.client.cmd_with_auth('ironic',
|
return self.client.cmd_with_auth('ironic',
|
||||||
action, flags, params)
|
action, flags, params,
|
||||||
|
merge_stderr=merge_stderr)
|
||||||
|
|
||||||
def _ironic_osc(self, action, flags='', params='', merge_stderr=False):
|
def _ironic_osc(self, action, flags='', params='', merge_stderr=False):
|
||||||
"""Execute baremetal commands via OpenStack Client."""
|
"""Execute baremetal commands via OpenStack Client."""
|
||||||
|
@@ -67,3 +67,11 @@ class IronicClientHelp(base.FunctionalTestBase):
|
|||||||
self.assertIn(caption, output)
|
self.assertIn(caption, output)
|
||||||
for string in subcommands:
|
for string in subcommands:
|
||||||
self.assertIn(string, output)
|
self.assertIn(string, output)
|
||||||
|
|
||||||
|
def test_warning_on_api_version(self):
|
||||||
|
result = self._ironic('help', merge_stderr=True)
|
||||||
|
self.assertIn('You are using the default API version', result)
|
||||||
|
|
||||||
|
result = self._ironic('help', flags='--ironic-api-version 1.9',
|
||||||
|
merge_stderr=True)
|
||||||
|
self.assertNotIn('You are using the default API version', result)
|
||||||
|
@@ -74,19 +74,18 @@ class ShellTest(utils.BaseTestCase):
|
|||||||
super(ShellTest, self).setUp()
|
super(ShellTest, self).setUp()
|
||||||
|
|
||||||
def shell(self, argstr):
|
def shell(self, argstr):
|
||||||
orig = sys.stdout
|
with mock.patch.object(sys, 'stdout', six.StringIO()):
|
||||||
try:
|
with mock.patch.object(sys, 'stderr', six.StringIO()):
|
||||||
sys.stdout = six.StringIO()
|
try:
|
||||||
_shell = ironic_shell.IronicShell()
|
_shell = ironic_shell.IronicShell()
|
||||||
_shell.main(argstr.split())
|
_shell.main(argstr.split())
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||||
self.assertEqual(0, exc_value.code)
|
self.assertEqual(0, exc_value.code)
|
||||||
finally:
|
finally:
|
||||||
out = sys.stdout.getvalue()
|
out = sys.stdout.getvalue()
|
||||||
sys.stdout.close()
|
err = sys.stderr.getvalue()
|
||||||
sys.stdout = orig
|
return out, err
|
||||||
return out
|
|
||||||
|
|
||||||
def test_help_unknown_command(self):
|
def test_help_unknown_command(self):
|
||||||
self.assertRaises(exc.CommandError, self.shell, 'help foofoo')
|
self.assertRaises(exc.CommandError, self.shell, 'help foofoo')
|
||||||
@@ -99,7 +98,7 @@ class ShellTest(utils.BaseTestCase):
|
|||||||
'for help on a specific command',
|
'for help on a specific command',
|
||||||
]
|
]
|
||||||
for argstr in ['--help', 'help']:
|
for argstr in ['--help', 'help']:
|
||||||
help_text = self.shell(argstr)
|
help_text = self.shell(argstr)[0]
|
||||||
for r in required:
|
for r in required:
|
||||||
self.assertThat(help_text,
|
self.assertThat(help_text,
|
||||||
matchers.MatchesRegex(r,
|
matchers.MatchesRegex(r,
|
||||||
@@ -114,7 +113,7 @@ class ShellTest(utils.BaseTestCase):
|
|||||||
'help chassis-show',
|
'help chassis-show',
|
||||||
]
|
]
|
||||||
for argstr in argstrings:
|
for argstr in argstrings:
|
||||||
help_text = self.shell(argstr)
|
help_text = self.shell(argstr)[0]
|
||||||
for r in required:
|
for r in required:
|
||||||
self.assertThat(help_text,
|
self.assertThat(help_text,
|
||||||
matchers.MatchesRegex(r, self.re_options))
|
matchers.MatchesRegex(r, self.re_options))
|
||||||
@@ -129,7 +128,7 @@ class ShellTest(utils.BaseTestCase):
|
|||||||
'help node-create',
|
'help node-create',
|
||||||
]
|
]
|
||||||
for argstr in argstrings:
|
for argstr in argstrings:
|
||||||
help_text = self.shell(argstr)
|
help_text = self.shell(argstr)[0]
|
||||||
for r in required:
|
for r in required:
|
||||||
self.assertThat(help_text,
|
self.assertThat(help_text,
|
||||||
matchers.MatchesRegex(r, self.re_options))
|
matchers.MatchesRegex(r, self.re_options))
|
||||||
@@ -144,7 +143,7 @@ class ShellTest(utils.BaseTestCase):
|
|||||||
'help port-create',
|
'help port-create',
|
||||||
]
|
]
|
||||||
for argstr in argstrings:
|
for argstr in argstrings:
|
||||||
help_text = self.shell(argstr)
|
help_text = self.shell(argstr)[0]
|
||||||
for r in required:
|
for r in required:
|
||||||
self.assertThat(help_text,
|
self.assertThat(help_text,
|
||||||
matchers.MatchesRegex(r, self.re_options))
|
matchers.MatchesRegex(r, self.re_options))
|
||||||
@@ -236,7 +235,7 @@ class ShellTest(utils.BaseTestCase):
|
|||||||
self.fail('CommandError not raised')
|
self.fail('CommandError not raised')
|
||||||
|
|
||||||
def test_bash_completion(self):
|
def test_bash_completion(self):
|
||||||
stdout = self.shell('bash-completion')
|
stdout = self.shell('bash-completion')[0]
|
||||||
# just check we have some output
|
# just check we have some output
|
||||||
required = [
|
required = [
|
||||||
'.*--driver_info',
|
'.*--driver_info',
|
||||||
@@ -249,8 +248,12 @@ class ShellTest(utils.BaseTestCase):
|
|||||||
matchers.MatchesRegex(r, self.re_options))
|
matchers.MatchesRegex(r, self.re_options))
|
||||||
|
|
||||||
def test_ironic_api_version(self):
|
def test_ironic_api_version(self):
|
||||||
self.shell('--ironic-api-version 1.2 help')
|
err = self.shell('--ironic-api-version 1.2 help')[1]
|
||||||
self.shell('--ironic-api-version latest help')
|
self.assertFalse(err)
|
||||||
|
|
||||||
|
err = self.shell('--ironic-api-version latest help')[1]
|
||||||
|
self.assertFalse(err)
|
||||||
|
|
||||||
self.assertRaises(exc.CommandError,
|
self.assertRaises(exc.CommandError,
|
||||||
self.shell, '--ironic-api-version 1.2.1 help')
|
self.shell, '--ironic-api-version 1.2.1 help')
|
||||||
|
|
||||||
@@ -258,6 +261,10 @@ class ShellTest(utils.BaseTestCase):
|
|||||||
self.assertRaises(exceptions.UnsupportedVersion,
|
self.assertRaises(exceptions.UnsupportedVersion,
|
||||||
self.shell, '--ironic-api-version 0.8 help')
|
self.shell, '--ironic-api-version 0.8 help')
|
||||||
|
|
||||||
|
def test_warning_on_no_version(self):
|
||||||
|
err = self.shell('help')[1]
|
||||||
|
self.assertIn('You are using the default API version', err)
|
||||||
|
|
||||||
|
|
||||||
class TestCase(testtools.TestCase):
|
class TestCase(testtools.TestCase):
|
||||||
|
|
||||||
|
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
deprecations:
|
||||||
|
- |
|
||||||
|
Currently, the default API version for the ``ironic`` tool is fixed to be
|
||||||
|
1.9. In the Queens release, it will be changed to the latest version
|
||||||
|
understood by both the client and the server. In this release a warning is
|
||||||
|
logged, if no explicit version is provided.
|
Reference in New Issue
Block a user