Add --include-pass option for grizzly backwards compat
Set X-Auth-User, X-Auth-Key on all stack commands to allow the latest python-heatclient to work on grizzly heat. Partial-Bug:1250731 Change-Id: I29d4785cf3520e809252b5aeab25cf471a88cde8
This commit is contained in:
parent
fa084b50fa
commit
6f3e0842e4
|
@ -53,6 +53,7 @@ class HTTPClient(object):
|
|||
self.username = kwargs.get('username')
|
||||
self.password = kwargs.get('password')
|
||||
self.region_name = kwargs.get('region_name')
|
||||
self.include_pass = kwargs.get('include_pass')
|
||||
self.connection_params = self.get_connection_params(endpoint, **kwargs)
|
||||
|
||||
@staticmethod
|
||||
|
@ -137,6 +138,8 @@ class HTTPClient(object):
|
|||
kwargs['headers'].setdefault('X-Auth-Url', self.auth_url)
|
||||
if self.region_name:
|
||||
kwargs['headers'].setdefault('X-Region-Name', self.region_name)
|
||||
if self.include_pass and not 'X-Auth-Key' in kwargs['headers']:
|
||||
kwargs['headers'].update(self.credentials_headers())
|
||||
|
||||
self.log_curl_request(method, url, kwargs)
|
||||
conn = self.get_connection()
|
||||
|
@ -160,7 +163,15 @@ class HTTPClient(object):
|
|||
body_str = ''.join([chunk for chunk in body_iter])
|
||||
self.log_http_response(resp, body_str)
|
||||
|
||||
if 400 <= resp.status < 600:
|
||||
if not 'X-Auth-Key' in kwargs['headers'] and \
|
||||
(resp.status == 401 or
|
||||
(resp.status == 500 and "(HTTP 401)" in body_str)):
|
||||
raise exc.HTTPUnauthorized("Authentication failed. Please try"
|
||||
" again with option "
|
||||
"--include-password or export "
|
||||
"HEAT_INCLUDE_PASSWORD=1\n%s"
|
||||
% body_str)
|
||||
elif 400 <= resp.status < 600:
|
||||
raise exc.from_response(resp, body_str)
|
||||
elif resp.status in (301, 302, 305):
|
||||
# Redirected. Reissue the request to the new location.
|
||||
|
|
|
@ -176,6 +176,11 @@ class HeatShell(object):
|
|||
parser.add_argument('--os_endpoint_type',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--include-password',
|
||||
default=bool(utils.env('HEAT_INCLUDE_PASSWORD')),
|
||||
action='store_true',
|
||||
help='Send os-username and os-password to heat')
|
||||
|
||||
return parser
|
||||
|
||||
def get_subcommand_parser(self, version):
|
||||
|
@ -328,7 +333,8 @@ class HeatShell(object):
|
|||
'auth_url': args.os_auth_url,
|
||||
'service_type': args.os_service_type,
|
||||
'endpoint_type': args.os_endpoint_type,
|
||||
'insecure': args.insecure
|
||||
'insecure': args.insecure,
|
||||
'include_pass': args.include_password
|
||||
}
|
||||
|
||||
endpoint = args.heat_url
|
||||
|
@ -346,7 +352,8 @@ class HeatShell(object):
|
|||
'key_file': args.key_file,
|
||||
'username': args.os_username,
|
||||
'password': args.os_password,
|
||||
'endpoint_type': args.os_endpoint_type
|
||||
'endpoint_type': args.os_endpoint_type,
|
||||
'include_pass': args.include_password
|
||||
}
|
||||
|
||||
if args.os_region_name:
|
||||
|
|
|
@ -100,6 +100,81 @@ class HttpClientTest(testtools.TestCase):
|
|||
self.assertEqual(resp.status, 200)
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_include_pass(self):
|
||||
# Record a 200
|
||||
fake200 = fakes.FakeHTTPResponse(
|
||||
200, 'OK',
|
||||
{'content-type': 'application/octet-stream'},
|
||||
'')
|
||||
|
||||
# no token or credentials
|
||||
mock_conn = http.httplib.HTTPConnection('example.com', 8004,
|
||||
timeout=600.0)
|
||||
mock_conn.request('GET', '/',
|
||||
headers={'Content-Type': 'application/octet-stream',
|
||||
'User-Agent': 'python-heatclient'})
|
||||
mock_conn.getresponse().AndReturn(fake200)
|
||||
|
||||
# credentials
|
||||
mock_conn = http.httplib.HTTPConnection('example.com', 8004,
|
||||
timeout=600.0)
|
||||
mock_conn.request('GET', '/',
|
||||
headers={'Content-Type': 'application/octet-stream',
|
||||
'User-Agent': 'python-heatclient',
|
||||
'X-Auth-Key': 'pass',
|
||||
'X-Auth-User': 'user'})
|
||||
mock_conn.getresponse().AndReturn(fake200)
|
||||
|
||||
# token suppresses credentials
|
||||
mock_conn = http.httplib.HTTPConnection('example.com', 8004,
|
||||
timeout=600.0)
|
||||
mock_conn.request('GET', '/',
|
||||
headers={'Content-Type': 'application/octet-stream',
|
||||
'User-Agent': 'python-heatclient',
|
||||
'X-Auth-Token': 'abcd1234',
|
||||
'X-Auth-Key': 'pass',
|
||||
'X-Auth-User': 'user'})
|
||||
mock_conn.getresponse().AndReturn(fake200)
|
||||
|
||||
# Replay, create client, assert
|
||||
self.m.ReplayAll()
|
||||
client = http.HTTPClient('http://example.com:8004')
|
||||
resp, body = client.raw_request('GET', '')
|
||||
self.assertEqual(200, resp.status)
|
||||
|
||||
client.username = 'user'
|
||||
client.password = 'pass'
|
||||
client.include_pass = True
|
||||
resp, body = client.raw_request('GET', '')
|
||||
self.assertEqual(200, resp.status)
|
||||
|
||||
client.auth_token = 'abcd1234'
|
||||
resp, body = client.raw_request('GET', '')
|
||||
self.assertEqual(200, resp.status)
|
||||
self.m.VerifyAll()
|
||||
|
||||
def test_not_include_pass(self):
|
||||
# Record a 200
|
||||
fake500 = fakes.FakeHTTPResponse(
|
||||
500, 'ERROR',
|
||||
{'content-type': 'application/octet-stream'},
|
||||
'(HTTP 401)')
|
||||
|
||||
# no token or credentials
|
||||
mock_conn = http.httplib.HTTPConnection('example.com', 8004,
|
||||
timeout=600.0)
|
||||
mock_conn.request('GET', '/',
|
||||
headers={'Content-Type': 'application/octet-stream',
|
||||
'User-Agent': 'python-heatclient'})
|
||||
mock_conn.getresponse().AndReturn(fake500)
|
||||
|
||||
# Replay, create client, assert
|
||||
self.m.ReplayAll()
|
||||
client = http.HTTPClient('http://example.com:8004')
|
||||
e = self.assertRaises(exc.HTTPUnauthorized,
|
||||
client.raw_request, 'GET', '')
|
||||
self.assertIn('include-password', str(e))
|
||||
|
||||
def test_region_name(self):
|
||||
# Record a 200
|
||||
fake200 = fakes.FakeHTTPResponse(
|
||||
|
|
Loading…
Reference in New Issue