Merge "Defect fix validation calls to UCP components"

This commit is contained in:
Bryan Strassner 2017-12-05 16:52:38 -05:00 committed by Gerrit Code Review
commit 49d1077f9a
3 changed files with 71 additions and 62 deletions

View File

@ -346,8 +346,8 @@ class ConfigdocsHelper(object):
# Constructs the design reference as json for use by other components # Constructs the design reference as json for use by other components
design_reference = { design_reference = {
"rel": "design", "rel": "design",
"href": "deckhand+{}/rendered-documents".format( "href": "deckhand+{}".format(DeckhandClient.get_path(
DeckhandPaths.RENDERED_REVISION_DOCS.value.format(revision_id) DeckhandPaths.RENDERED_REVISION_DOCS).format(revision_id)
), ),
"type": "application/x-yaml" "type": "application/x-yaml"
} }
@ -374,20 +374,18 @@ class ConfigdocsHelper(object):
# create a holder for things we need back from the threads # create a holder for things we need back from the threads
response = {'response': None} response = {'response': None}
exception = {'exception': None} exception = {'exception': None}
design_ref = ConfigdocsHelper._get_design_reference(revision_id)
validation_threads.append( validation_threads.append(
{ {
'thread': threading.Thread( 'thread': threading.Thread(
target=ConfigdocsHelper._get_validations_for_component, target=ConfigdocsHelper._get_validations_for_component,
args=(
endpoint['url'],
ConfigdocsHelper._get_design_reference(
revision_id
),
response,
exception,
ctx.external_marker
),
kwargs={ kwargs={
'url': endpoint['url'],
'design_reference': design_ref,
'response': response,
'exception': exception,
'context_marker': ctx.external_marker,
'thread_name': endpoint['name'],
'log_extra': { 'log_extra': {
'req_id': ctx.request_id, 'req_id': ctx.request_id,
'external_ctx': ctx.external_marker, 'external_ctx': ctx.external_marker,
@ -409,26 +407,44 @@ class ConfigdocsHelper(object):
response, response,
exception, exception,
context_marker, context_marker,
thread_name,
**kwargs): **kwargs):
# Invoke the POST for validation # Invoke the POST for validation
try: try:
headers = { headers = {
'X-Context-Marker': context_marker, 'X-Context-Marker': context_marker,
'X-Auth-Token': get_token(), 'X-Auth-Token': get_token(),
'content-type': 'application/x-yaml' 'content-type': 'application/json'
} }
http_resp = requests.post(url, http_resp = requests.post(url,
headers=headers, headers=headers,
data=design_reference, data=design_reference,
timeout=(5, 30)) timeout=(5, 30))
http_resp.raise_for_status() # 400 response is "valid" failure to validate. > 400 is a problem.
raw_response = http_resp.decode('utf-8') if http_resp.status_code > 400:
response_dict = json.loads(raw_response) http_resp.raise_for_status()
response_dict = http_resp.json()
response['response'] = response_dict response['response'] = response_dict
except Exception as ex: except Exception as ex:
# catch anything exceptional as a failure to validate # catch anything exceptional as a failure to run validations
LOG.error(ex) unable_str = '{} unable to validate configdocs'.format(thread_name)
LOG.error("%s. Exception follows.", unable_str)
LOG.error(str(ex))
response['response'] = {
'details': {
'messageList': [
{
'message': unable_str,
'error': True
},
{
'message': str(ex),
'error': True
}
]
}
}
exception['exception'] = ex exception['exception'] = ex
def get_validations_for_revision(self, revision_id): def get_validations_for_revision(self, revision_id):
@ -456,37 +472,25 @@ class ConfigdocsHelper(object):
# check on the response, extract the validations # check on the response, extract the validations
error_count = 0 error_count = 0
for validation_thread in validation_threads: for validation_thread in validation_threads:
val_response = validation_thread.get('response')['response'] th_name = validation_thread.get('name')
if (not val_response or val_response = validation_thread.get('response',
validation_thread.get('exception')['exception']): {}).get('response')
# exception was raised, or no body was returned. LOG.debug("Validation from: %s response: %s",
raise AppError( th_name, str(val_response))
title='Unable to properly validate configdocs', if validation_thread.get('exception', {}).get('exception'):
description=( LOG.error('Invocation of validation by %s has failed', th_name)
'Invocation of validation by {} has failed'.format(
validation_thread.get('name')
)
),
status=falcon.HTTP_500,
retry=False,
)
if not val_response:
raise AppError(
title='An invalid response was returned by validation',
description='No valid response status from {}'.format(
validation_thread.get('name')),
status=falcon.HTTP_500,
retry=False,
)
# invalid status needs collection of messages # invalid status needs collection of messages
# valid status means that it passed. No messages to collect # valid status means that it passed. No messages to collect
msg_list = val_response.get('details').get('messageList') if val_response.get('details') is None:
msg_list = [{'message': str(val_response), 'error': True}]
else:
msg_list = val_response.get('details').get('messageList', [])
for msg in msg_list: for msg in msg_list:
if msg.get('error'): if msg.get('error'):
error_count = error_count + 1 error_count = error_count + 1
resp_msgs.append( resp_msgs.append(
{ {
'name': validation_thread.get('name'), 'name': th_name,
'message': msg.get('message'), 'message': msg.get('message'),
'error': True 'error': True
} }
@ -494,7 +498,7 @@ class ConfigdocsHelper(object):
else: else:
resp_msgs.append( resp_msgs.append(
{ {
'name': validation_thread.get('name'), 'name': th_name,
'message': msg.get('message'), 'message': msg.get('message'),
'error': False 'error': False
} }

View File

@ -153,7 +153,7 @@ class DeckhandClient(object):
).format(revision_id, tag) ).format(revision_id, tag)
response = self._post_request(url) response = self._post_request(url)
response.raise_for_status() self._handle_bad_response(response)
return yaml.safe_load(response.text) return yaml.safe_load(response.text)
def rollback(self, target_revision_id): def rollback(self, target_revision_id):

View File

@ -26,6 +26,7 @@ from shipyard_airflow.control.configdocs.configdocs_helper import (
) )
from shipyard_airflow.control.configdocs.deckhand_client import ( from shipyard_airflow.control.configdocs.deckhand_client import (
DeckhandClient, DeckhandClient,
DeckhandPaths,
DeckhandResponseError, DeckhandResponseError,
NoRevisionsExistError NoRevisionsExistError
) )
@ -539,25 +540,29 @@ def test_get_validations_for_revision():
""" """
Tets the functionality of the get_validations_for_revision method Tets the functionality of the get_validations_for_revision method
""" """
helper = ConfigdocsHelper(CTX) with patch('shipyard_airflow.control.configdocs.deckhand_client.'
hold_ve = helper.__class__._get_validation_endpoints 'DeckhandClient.get_path') as mock_get_path:
hold_vfc = helper.__class__._get_validations_for_component mock_get_path.return_value = 'path{}'
helper.__class__._get_validation_endpoints = ( helper = ConfigdocsHelper(CTX)
_fake_get_validation_endpoints hold_ve = helper.__class__._get_validation_endpoints
) hold_vfc = helper.__class__._get_validations_for_component
helper.__class__._get_validations_for_component = ( helper.__class__._get_validation_endpoints = (
_fake_get_validations_for_component _fake_get_validation_endpoints
) )
helper._get_deckhand_validations = lambda revision_id: [] helper.__class__._get_validations_for_component = (
try: _fake_get_validations_for_component
val_status = helper.get_validations_for_revision(3) )
err_count = val_status['details']['errorCount'] helper._get_deckhand_validations = lambda revision_id: []
err_list_count = len(val_status['details']['messageList']) try:
assert err_count == err_list_count val_status = helper.get_validations_for_revision(3)
assert val_status['details']['errorCount'] == 4 err_count = val_status['details']['errorCount']
finally: err_list_count = len(val_status['details']['messageList'])
helper.__class__._get_validation_endpoints = hold_ve assert err_count == err_list_count
helper.__class__._get_validations_for_component = hold_vfc assert val_status['details']['errorCount'] == 4
finally:
helper.__class__._get_validation_endpoints = hold_ve
helper.__class__._get_validations_for_component = hold_vfc
mock_get_path.assert_called_with(DeckhandPaths.RENDERED_REVISION_DOCS)
FK_VAL_BASE_RESP = FakeResponse(status_code=200, text=""" FK_VAL_BASE_RESP = FakeResponse(status_code=200, text="""