Adds tty password entry for ironicclient
Added functionality from keystoneclient to fallback to the tty for password entry if no password is given via the environment or the --os-password option. Change-Id: I92da7112221c77efc220374617d503dc2184363e Closes-Bug: 1382146
This commit is contained in:
parent
c349063d36
commit
9d6137380b
|
@ -19,6 +19,7 @@ Command-line interface to the OpenStack Bare Metal Provisioning
|
|||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import getpass
|
||||
import logging
|
||||
import sys
|
||||
|
||||
|
@ -372,10 +373,22 @@ class IronicShell(object):
|
|||
"either --os-username or via "
|
||||
"env[OS_USERNAME]"))
|
||||
|
||||
if not args.os_password:
|
||||
# No password, If we've got a tty, try prompting for it
|
||||
if hasattr(sys.stdin, 'isatty') and sys.stdin.isatty():
|
||||
# Check for Ctl-D
|
||||
try:
|
||||
args.os_password = getpass.getpass(
|
||||
'OpenStack Password: ')
|
||||
except EOFError:
|
||||
pass
|
||||
# No password because we didn't have a tty or the
|
||||
# user Ctl-D when prompted.
|
||||
if not args.os_password:
|
||||
raise exc.CommandError(_("You must provide a password via "
|
||||
"either --os-password or via "
|
||||
"env[OS_PASSWORD]"))
|
||||
"either --os-password, "
|
||||
"env[OS_PASSWORD], "
|
||||
"or prompted response"))
|
||||
|
||||
if not (args.os_tenant_id or args.os_tenant_name or
|
||||
args.os_project_id or args.os_project_name):
|
||||
|
|
|
@ -19,8 +19,10 @@ import sys
|
|||
import fixtures
|
||||
import httplib2
|
||||
import httpretty
|
||||
from keystoneclient import exceptions as keystone_exc
|
||||
from keystoneclient.fixture import v2 as ks_v2_fixture
|
||||
from keystoneclient.fixture import v3 as ks_v3_fixture
|
||||
import mock
|
||||
import six
|
||||
import testtools
|
||||
from testtools import matchers
|
||||
|
@ -33,7 +35,7 @@ from ironicclient.tests import utils
|
|||
FAKE_ENV = {'OS_USERNAME': 'username',
|
||||
'OS_PASSWORD': 'password',
|
||||
'OS_TENANT_NAME': 'tenant_name',
|
||||
'OS_AUTH_URL': 'http://no.where'}
|
||||
'OS_AUTH_URL': 'http://no.where/v2.0/'}
|
||||
|
||||
FAKE_ENV_KEYSTONE_V2 = {
|
||||
'OS_USERNAME': 'username',
|
||||
|
@ -76,7 +78,6 @@ class ShellTest(utils.BaseTestCase):
|
|||
out = sys.stdout.getvalue()
|
||||
sys.stdout.close()
|
||||
sys.stdout = orig
|
||||
|
||||
return out
|
||||
|
||||
def test_help_unknown_command(self):
|
||||
|
@ -119,6 +120,42 @@ class ShellTest(utils.BaseTestCase):
|
|||
self.make_env(exclude='OS_USERNAME')
|
||||
self.test_help()
|
||||
|
||||
@mock.patch('sys.stdin', side_effect=mock.MagicMock)
|
||||
@mock.patch('getpass.getpass', return_value='password')
|
||||
def test_password_prompted(self, mock_getpass, mock_stdin):
|
||||
self.make_env(exclude='OS_PASSWORD')
|
||||
# We will get a Connection Refused because there is no keystone.
|
||||
self.assertRaises(keystone_exc.ConnectionRefused,
|
||||
self.shell, 'node-list')
|
||||
# Make sure we are actually prompted.
|
||||
mock_getpass.assert_called_with('OpenStack Password: ')
|
||||
|
||||
@mock.patch('sys.stdin', side_effect=mock.MagicMock)
|
||||
@mock.patch('getpass.getpass', side_effect=EOFError)
|
||||
def test_password_prompted_ctrlD(self, mock_getpass, mock_stdin):
|
||||
self.make_env(exclude='OS_PASSWORD')
|
||||
# We should get Command Error because we mock Ctl-D.
|
||||
self.assertRaises(exc.CommandError,
|
||||
self.shell, 'node-list')
|
||||
# Make sure we are actually prompted.
|
||||
mock_getpass.assert_called_with('OpenStack Password: ')
|
||||
|
||||
@mock.patch('sys.stdin')
|
||||
def test_no_password_no_tty(self, mock_stdin):
|
||||
# delete the isatty attribute so that we do not get
|
||||
# prompted when manually running the tests
|
||||
del mock_stdin.isatty
|
||||
required = ('You must provide a password'
|
||||
' via either --os-password, env[OS_PASSWORD],'
|
||||
' or prompted response',)
|
||||
self.make_env(exclude='OS_PASSWORD')
|
||||
try:
|
||||
self.shell('node-list')
|
||||
except exc.CommandError as message:
|
||||
self.assertEqual(required, message.args)
|
||||
else:
|
||||
self.fail('CommandError not raised')
|
||||
|
||||
def test_bash_completion(self):
|
||||
stdout = self.shell('bash-completion')
|
||||
# just check we have some output
|
||||
|
|
Loading…
Reference in New Issue