Merge "Use betamax hooks to mask fixture results"
This commit is contained in:
commit
fe4a9ca120
56
keystoneauth1/fixture/hooks.py
Normal file
56
keystoneauth1/fixture/hooks.py
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# Copyright (c) 2016 Hewlett-Packard Enterprise Development Company, L.P.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
"""Custom hooks for betamax and keystoneauth.
|
||||||
|
|
||||||
|
Module providing a set of hooks specially designed for
|
||||||
|
interacting with clouds and keystone authentication.
|
||||||
|
|
||||||
|
:author: Yolanda Robla
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
def mask_credentials(content):
|
||||||
|
"""it will mask all credentials for a given content."""
|
||||||
|
content = re.sub(r'"tenantName": "(.*?)"',
|
||||||
|
'"tenantName": "dummy"', content)
|
||||||
|
content = re.sub(r'"username": "(.*?)"',
|
||||||
|
'"username": "dummy"', content)
|
||||||
|
content = re.sub(r'"password": "(.*?)"',
|
||||||
|
'"password": "********"', content)
|
||||||
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
def update_expiration(content):
|
||||||
|
"""it will set token expiration in the long future."""
|
||||||
|
content = re.sub(r'"expires": "(.*?)"',
|
||||||
|
'"expires": "9999-12-31T23:59:59Z"', content)
|
||||||
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
def pre_record_hook(interaction, cassette):
|
||||||
|
"""Hook to mask saved data.
|
||||||
|
|
||||||
|
This hook will be triggered before saving the interaction, and
|
||||||
|
will perform two tasks:
|
||||||
|
- mask user, project and password in the saved data
|
||||||
|
- set token expiration time to an inifinite time.
|
||||||
|
"""
|
||||||
|
request_body = interaction.data['request']['body']
|
||||||
|
request_body['string'] = mask_credentials(
|
||||||
|
request_body['string'])
|
||||||
|
response_body = interaction.data['response']['body']
|
||||||
|
response_body['string'] = update_expiration(mask_credentials(
|
||||||
|
response_body['string']))
|
@ -19,19 +19,22 @@ import fixtures
|
|||||||
import mock
|
import mock
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
from keystoneauth1.fixture import hooks
|
||||||
from keystoneauth1 import session
|
from keystoneauth1 import session
|
||||||
|
|
||||||
|
|
||||||
class BetamaxFixture(fixtures.Fixture):
|
class BetamaxFixture(fixtures.Fixture):
|
||||||
|
|
||||||
def __init__(self, cassette_name, cassette_library_dir=None,
|
def __init__(self, cassette_name, cassette_library_dir=None,
|
||||||
serializer=None, record=False):
|
serializer=None, record=False,
|
||||||
|
pre_record_hook=hooks.pre_record_hook):
|
||||||
self.cassette_library_dir = cassette_library_dir
|
self.cassette_library_dir = cassette_library_dir
|
||||||
self.serializer = serializer
|
self.serializer = serializer
|
||||||
self.record = record
|
self.record = record
|
||||||
self.cassette_name = cassette_name
|
self.cassette_name = cassette_name
|
||||||
if serializer:
|
if serializer:
|
||||||
betamax.Betamax.register_serializer(serializer)
|
betamax.Betamax.register_serializer(serializer)
|
||||||
|
self.pre_record_hook = pre_record_hook
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(BetamaxFixture, self).setUp()
|
super(BetamaxFixture, self).setUp()
|
||||||
@ -53,6 +56,9 @@ def _construct_session_with_betamax(fixture, session_obj=None):
|
|||||||
# Use TCPKeepAliveAdapter to fix bug 1323862
|
# Use TCPKeepAliveAdapter to fix bug 1323862
|
||||||
for scheme in list(session_obj.adapters.keys()):
|
for scheme in list(session_obj.adapters.keys()):
|
||||||
session_obj.mount(scheme, session.TCPKeepAliveAdapter())
|
session_obj.mount(scheme, session.TCPKeepAliveAdapter())
|
||||||
|
|
||||||
|
with betamax.Betamax.configure() as config:
|
||||||
|
config.before_record(callback=fixture.pre_record_hook)
|
||||||
fixture.recorder = betamax.Betamax(
|
fixture.recorder = betamax.Betamax(
|
||||||
session_obj, cassette_library_dir=fixture.cassette_library_dir)
|
session_obj, cassette_library_dir=fixture.cassette_library_dir)
|
||||||
|
|
||||||
|
116
keystoneauth1/tests/unit/test_betamax_hooks.py
Normal file
116
keystoneauth1/tests/unit/test_betamax_hooks.py
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import betamax
|
||||||
|
import json
|
||||||
|
from requests import models
|
||||||
|
import testtools
|
||||||
|
|
||||||
|
try:
|
||||||
|
from requests.packages.urllib3._collections import HTTPHeaderDict
|
||||||
|
except ImportError:
|
||||||
|
from betamax.headers import HTTPHeaderDict
|
||||||
|
|
||||||
|
from keystoneauth1.fixture import hooks
|
||||||
|
|
||||||
|
|
||||||
|
class TestBetamaxHooks(testtools.TestCase):
|
||||||
|
|
||||||
|
def test_pre_record_hook(self):
|
||||||
|
with betamax.Betamax.configure() as config:
|
||||||
|
config.before_record(callback=hooks.pre_record_hook)
|
||||||
|
|
||||||
|
cassette = betamax.cassette.Cassette(
|
||||||
|
'test_pre_record_hook', 'json', record_mode=None,
|
||||||
|
cassette_library_dir='keystoneauth1/tests/unit/data')
|
||||||
|
|
||||||
|
# Create a new object to serialize
|
||||||
|
r = models.Response()
|
||||||
|
r.status_code = 200
|
||||||
|
r.reason = 'OK'
|
||||||
|
r.encoding = 'utf-8'
|
||||||
|
r.headers = {}
|
||||||
|
r.url = 'http://192.168.0.19:35357/'
|
||||||
|
|
||||||
|
body_content = {
|
||||||
|
'auth': {
|
||||||
|
'passwordCredentials': {
|
||||||
|
'username': 'user',
|
||||||
|
'password': 'password'
|
||||||
|
},
|
||||||
|
'tenantName': 'dummy',
|
||||||
|
},
|
||||||
|
'access': {
|
||||||
|
'token': {
|
||||||
|
'expires': '2001-01-01T00:00:00Z'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body_content = {
|
||||||
|
'body': {
|
||||||
|
'string': json.dumps(body_content),
|
||||||
|
'encoding': 'utf-8',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
betamax.util.add_urllib3_response(
|
||||||
|
body_content, r,
|
||||||
|
HTTPHeaderDict({'Accept': 'application/json'}))
|
||||||
|
response = r
|
||||||
|
|
||||||
|
# Create an associated request
|
||||||
|
r = models.Request()
|
||||||
|
r.method = 'GET'
|
||||||
|
r.url = 'http://192.168.0.19:35357/'
|
||||||
|
r.headers = {}
|
||||||
|
r.data = {}
|
||||||
|
response.request = r.prepare()
|
||||||
|
response.request.headers.update(
|
||||||
|
{'User-Agent': 'betamax/test header'}
|
||||||
|
)
|
||||||
|
|
||||||
|
response.request.body = json.dumps({
|
||||||
|
'auth': {
|
||||||
|
'passwordCredentials': {
|
||||||
|
'username': 'user',
|
||||||
|
'password': 'password'
|
||||||
|
},
|
||||||
|
'tenantName': 'dummy'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
interaction = cassette.save_interaction(response, response.request)
|
||||||
|
|
||||||
|
# check that all values have been masked
|
||||||
|
response_content = json.loads(
|
||||||
|
interaction.data['response']['body']['string'])
|
||||||
|
self.assertEqual(
|
||||||
|
response_content['access']['token']['expires'],
|
||||||
|
u'9999-12-31T23:59:59Z')
|
||||||
|
self.assertEqual(response_content['auth']['tenantName'], u'dummy')
|
||||||
|
self.assertEqual(
|
||||||
|
response_content['auth']['passwordCredentials']['username'],
|
||||||
|
u'dummy')
|
||||||
|
self.assertEqual(
|
||||||
|
response_content['auth']['passwordCredentials']['password'],
|
||||||
|
u'********')
|
||||||
|
|
||||||
|
request_content = json.loads(
|
||||||
|
interaction.data['response']['body']['string'])
|
||||||
|
self.assertEqual(request_content['auth']['tenantName'], u'dummy')
|
||||||
|
self.assertEqual(
|
||||||
|
request_content['auth']['passwordCredentials']['username'],
|
||||||
|
u'dummy')
|
||||||
|
self.assertEqual(
|
||||||
|
request_content['auth']['passwordCredentials']['password'],
|
||||||
|
u'********')
|
Loading…
Reference in New Issue
Block a user