Shipyard API for Configdocs Status
Shipyard API to discover buffered and committed collections of configdocs 1 of 4 Commits (API Client, CLI, Documentation are in separate commits) API -added url to api.py and policy.py -added ConfigDocsStatusResource for on_get call in configdocs_api.py -obtain the status of the configdocs in configdocs_helper.py -unit tests are located in test_configdocs_api.py and test_configdocs_helper.py Change-Id: Iaf3f6d9113ae778c5efd8b3df1a8ebd16c385c14
This commit is contained in:
parent
609bc0a624
commit
9aa13ac5e9
@ -29,7 +29,8 @@ from shipyard_airflow.control.af_monitoring.workflows_api import (
|
|||||||
from shipyard_airflow.control.base import BaseResource, ShipyardRequest
|
from shipyard_airflow.control.base import BaseResource, ShipyardRequest
|
||||||
from shipyard_airflow.control.configdocs.configdocs_api import (
|
from shipyard_airflow.control.configdocs.configdocs_api import (
|
||||||
CommitConfigDocsResource,
|
CommitConfigDocsResource,
|
||||||
ConfigDocsResource
|
ConfigDocsResource,
|
||||||
|
ConfigDocsStatusResource
|
||||||
)
|
)
|
||||||
from shipyard_airflow.control.configdocs.rendered_configdocs_api import \
|
from shipyard_airflow.control.configdocs.rendered_configdocs_api import \
|
||||||
RenderedConfigDocsResource
|
RenderedConfigDocsResource
|
||||||
@ -66,6 +67,7 @@ def start_api():
|
|||||||
ActionsStepsResource()),
|
ActionsStepsResource()),
|
||||||
('/actions/{action_id}/validations/{validation_id}',
|
('/actions/{action_id}/validations/{validation_id}',
|
||||||
ActionsValidationsResource()),
|
ActionsValidationsResource()),
|
||||||
|
('/configdocs', ConfigDocsStatusResource()),
|
||||||
('/configdocs/{collection_id}', ConfigDocsResource()),
|
('/configdocs/{collection_id}', ConfigDocsResource()),
|
||||||
('/commitconfigdocs', CommitConfigDocsResource()),
|
('/commitconfigdocs', CommitConfigDocsResource()),
|
||||||
('/renderedconfigdocs', RenderedConfigDocsResource()),
|
('/renderedconfigdocs', RenderedConfigDocsResource()),
|
||||||
|
@ -22,15 +22,27 @@ from shipyard_airflow.control.configdocs import configdocs_helper
|
|||||||
from shipyard_airflow.control.api_lock import (api_lock, ApiLockType)
|
from shipyard_airflow.control.api_lock import (api_lock, ApiLockType)
|
||||||
from shipyard_airflow.control.base import BaseResource
|
from shipyard_airflow.control.base import BaseResource
|
||||||
from shipyard_airflow.control.configdocs.configdocs_helper import (
|
from shipyard_airflow.control.configdocs.configdocs_helper import (
|
||||||
BufferMode,
|
BufferMode, ConfigdocsHelper)
|
||||||
ConfigdocsHelper
|
|
||||||
)
|
|
||||||
from shipyard_airflow.errors import ApiError
|
from shipyard_airflow.errors import ApiError
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
VERSION_VALUES = ['buffer', 'committed']
|
VERSION_VALUES = ['buffer', 'committed']
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigDocsStatusResource(BaseResource):
|
||||||
|
"""
|
||||||
|
Configdocs Status handles the retrieval of the configuration documents'
|
||||||
|
statuses
|
||||||
|
"""
|
||||||
|
|
||||||
|
@policy.ApiEnforcer('workflow_orchestrator:get_configdocs_status')
|
||||||
|
def on_get(self, req, resp):
|
||||||
|
"""Returns a list of the configdocs and their statuses"""
|
||||||
|
helper = ConfigdocsHelper(req.context)
|
||||||
|
resp.body = helper.get_configdocs_status()
|
||||||
|
resp.status = falcon.HTTP_200
|
||||||
|
|
||||||
|
|
||||||
class ConfigDocsResource(BaseResource):
|
class ConfigDocsResource(BaseResource):
|
||||||
"""
|
"""
|
||||||
Configdocs handles the creation and retrieval of configuration
|
Configdocs handles the creation and retrieval of configuration
|
||||||
@ -49,8 +61,7 @@ class ConfigDocsResource(BaseResource):
|
|||||||
helper=helper,
|
helper=helper,
|
||||||
collection_id=collection_id,
|
collection_id=collection_id,
|
||||||
document_data=document_data,
|
document_data=document_data,
|
||||||
buffer_mode_param=req.params.get('buffermode')
|
buffer_mode_param=req.params.get('buffermode'))
|
||||||
)
|
|
||||||
resp.location = '/api/v1.0/configdocs/{}'.format(collection_id)
|
resp.location = '/api/v1.0/configdocs/{}'.format(collection_id)
|
||||||
resp.body = self.to_json(validations)
|
resp.body = self.to_json(validations)
|
||||||
resp.status = falcon.HTTP_201
|
resp.status = falcon.HTTP_201
|
||||||
@ -65,10 +76,7 @@ class ConfigDocsResource(BaseResource):
|
|||||||
helper = ConfigdocsHelper(req.context)
|
helper = ConfigdocsHelper(req.context)
|
||||||
# Not reformatting to JSON or YAML since just passing through
|
# Not reformatting to JSON or YAML since just passing through
|
||||||
resp.body = self.get_collection(
|
resp.body = self.get_collection(
|
||||||
helper=helper,
|
helper=helper, collection_id=collection_id, version=version)
|
||||||
collection_id=collection_id,
|
|
||||||
version=version
|
|
||||||
)
|
|
||||||
resp.append_header('Content-Type', 'application/x-yaml')
|
resp.append_header('Content-Type', 'application/x-yaml')
|
||||||
resp.status = falcon.HTTP_200
|
resp.status = falcon.HTTP_200
|
||||||
|
|
||||||
@ -78,16 +86,11 @@ class ConfigDocsResource(BaseResource):
|
|||||||
raise ApiError(
|
raise ApiError(
|
||||||
title='Invalid version query parameter specified',
|
title='Invalid version query parameter specified',
|
||||||
description=(
|
description=(
|
||||||
'version must be {}'.format(', '.join(VERSION_VALUES))
|
'version must be {}'.format(', '.join(VERSION_VALUES))),
|
||||||
),
|
|
||||||
status=falcon.HTTP_400,
|
status=falcon.HTTP_400,
|
||||||
retry=False,
|
retry=False, )
|
||||||
)
|
|
||||||
|
|
||||||
def get_collection(self,
|
def get_collection(self, helper, collection_id, version='buffer'):
|
||||||
helper,
|
|
||||||
collection_id,
|
|
||||||
version='buffer'):
|
|
||||||
"""
|
"""
|
||||||
Attempts to retrieve the specified collection of documents
|
Attempts to retrieve the specified collection of documents
|
||||||
either from the buffer or committed version, as specified
|
either from the buffer or committed version, as specified
|
||||||
@ -107,15 +110,10 @@ class ConfigDocsResource(BaseResource):
|
|||||||
else:
|
else:
|
||||||
buffer_mode = ConfigdocsHelper.get_buffer_mode(buffer_mode_param)
|
buffer_mode = ConfigdocsHelper.get_buffer_mode(buffer_mode_param)
|
||||||
|
|
||||||
if helper.is_buffer_valid_for_bucket(collection_id,
|
if helper.is_buffer_valid_for_bucket(collection_id, buffer_mode):
|
||||||
buffer_mode):
|
buffer_revision = helper.add_collection(collection_id,
|
||||||
buffer_revision = helper.add_collection(
|
document_data)
|
||||||
collection_id,
|
return helper.get_deckhand_validation_status(buffer_revision)
|
||||||
document_data
|
|
||||||
)
|
|
||||||
return helper.get_deckhand_validation_status(
|
|
||||||
buffer_revision
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
raise ApiError(
|
raise ApiError(
|
||||||
title='Invalid collection specified for buffer',
|
title='Invalid collection specified for buffer',
|
||||||
@ -127,8 +125,7 @@ class ConfigDocsResource(BaseResource):
|
|||||||
'Setting a different buffermode may '
|
'Setting a different buffermode may '
|
||||||
'provide the desired functionality')
|
'provide the desired functionality')
|
||||||
}],
|
}],
|
||||||
retry=False,
|
retry=False, )
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class CommitConfigDocsResource(BaseResource):
|
class CommitConfigDocsResource(BaseResource):
|
||||||
@ -163,8 +160,7 @@ class CommitConfigDocsResource(BaseResource):
|
|||||||
title=CommitConfigDocsResource.unable_to_commmit,
|
title=CommitConfigDocsResource.unable_to_commmit,
|
||||||
description='There are no documents in the buffer to commit',
|
description='There are no documents in the buffer to commit',
|
||||||
status=falcon.HTTP_409,
|
status=falcon.HTTP_409,
|
||||||
retry=True
|
retry=True)
|
||||||
)
|
|
||||||
validations = helper.get_validations_for_buffer()
|
validations = helper.get_validations_for_buffer()
|
||||||
if force or validations.get('status') == 'Success':
|
if force or validations.get('status') == 'Success':
|
||||||
helper.tag_buffer(configdocs_helper.COMMITTED)
|
helper.tag_buffer(configdocs_helper.COMMITTED)
|
||||||
@ -173,8 +169,7 @@ class CommitConfigDocsResource(BaseResource):
|
|||||||
validations['code'] = falcon.HTTP_200
|
validations['code'] = falcon.HTTP_200
|
||||||
if validations.get('message'):
|
if validations.get('message'):
|
||||||
validations['message'] = (
|
validations['message'] = (
|
||||||
validations['message'] + ' FORCED SUCCESS'
|
validations['message'] + ' FORCED SUCCESS')
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
validations['message'] = 'FORCED SUCCESS'
|
validations['message'] = 'FORCED SUCCESS'
|
||||||
return validations
|
return validations
|
||||||
|
@ -26,18 +26,10 @@ from oslo_config import cfg
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from shipyard_airflow.control.configdocs.deckhand_client import (
|
from shipyard_airflow.control.configdocs.deckhand_client import (
|
||||||
DeckhandClient,
|
DeckhandClient, DeckhandPaths, DeckhandRejectedInputError,
|
||||||
DeckhandPaths,
|
DeckhandResponseError, DocumentExistsElsewhereError, NoRevisionsExistError)
|
||||||
DeckhandRejectedInputError,
|
|
||||||
DeckhandResponseError,
|
|
||||||
DocumentExistsElsewhereError,
|
|
||||||
NoRevisionsExistError
|
|
||||||
)
|
|
||||||
from shipyard_airflow.control.service_endpoints import (
|
from shipyard_airflow.control.service_endpoints import (
|
||||||
Endpoints,
|
Endpoints, get_endpoint, get_token)
|
||||||
get_endpoint,
|
|
||||||
get_token
|
|
||||||
)
|
|
||||||
from shipyard_airflow.errors import ApiError, AppError
|
from shipyard_airflow.errors import ApiError, AppError
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
@ -112,28 +104,23 @@ class ConfigdocsHelper(object):
|
|||||||
|
|
||||||
# If there is no committed revision, then it's 0.
|
# If there is no committed revision, then it's 0.
|
||||||
# new revision is ok because we just checked for buffer emptiness
|
# new revision is ok because we just checked for buffer emptiness
|
||||||
old_revision_id = self._get_committed_rev_id()
|
old_revision_id = self._get_committed_rev_id() or 0
|
||||||
if old_revision_id is None:
|
|
||||||
old_revision_id = 0
|
|
||||||
try:
|
try:
|
||||||
diff = self.deckhand.get_diff(
|
diff = self.deckhand.get_diff(
|
||||||
old_revision_id=old_revision_id,
|
old_revision_id=old_revision_id,
|
||||||
new_revision_id=self._get_buffer_rev_id()
|
new_revision_id=self._get_buffer_rev_id())
|
||||||
)
|
|
||||||
# the collection is in the buffer if it's not unmodified
|
# the collection is in the buffer if it's not unmodified
|
||||||
return diff.get(collection_id, 'unmodified') != 'unmodified'
|
return diff.get(collection_id, 'unmodified') != 'unmodified'
|
||||||
|
|
||||||
except DeckhandResponseError as drex:
|
except DeckhandResponseError as drex:
|
||||||
raise AppError(
|
raise AppError(
|
||||||
title='Unable to retrieve revisions',
|
title='Unable to retrieve revisions',
|
||||||
description=(
|
description=(
|
||||||
'Deckhand has responded unexpectedly: {}:{}'.format(
|
'Deckhand has responded unexpectedly: {}:{}'.format(
|
||||||
drex.status_code,
|
drex.status_code, drex.response_message)),
|
||||||
drex.response_message
|
|
||||||
)
|
|
||||||
),
|
|
||||||
status=falcon.HTTP_500,
|
status=falcon.HTTP_500,
|
||||||
retry=False,
|
retry=False, )
|
||||||
)
|
|
||||||
|
|
||||||
def is_buffer_valid_for_bucket(self, collection_id, buffermode):
|
def is_buffer_valid_for_bucket(self, collection_id, buffermode):
|
||||||
"""
|
"""
|
||||||
@ -166,6 +153,56 @@ class ConfigdocsHelper(object):
|
|||||||
self.deckhand.rollback(committed_rev_id)
|
self.deckhand.rollback(committed_rev_id)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def get_configdocs_status(self):
|
||||||
|
"""
|
||||||
|
Returns a list of the configdocs, committed or in buffer, and their
|
||||||
|
current committed and buffer statuses
|
||||||
|
"""
|
||||||
|
configdocs_status = []
|
||||||
|
|
||||||
|
# If there is no committed revision, then it's 0.
|
||||||
|
# new revision is ok because we just checked for buffer emptiness
|
||||||
|
old_revision_id = self._get_committed_rev_id() or 0
|
||||||
|
new_revision_id = self._get_buffer_rev_id() or old_revision_id
|
||||||
|
|
||||||
|
try:
|
||||||
|
diff = self.deckhand.get_diff(
|
||||||
|
old_revision_id=old_revision_id,
|
||||||
|
new_revision_id=new_revision_id)
|
||||||
|
|
||||||
|
except DeckhandResponseError as drex:
|
||||||
|
raise AppError(
|
||||||
|
title='Unable to retrieve revisions',
|
||||||
|
description=(
|
||||||
|
'Deckhand has responded unexpectedly: {}:{}'.format(
|
||||||
|
drex.status_code, drex.response_message)),
|
||||||
|
status=falcon.HTTP_500,
|
||||||
|
retry=False, )
|
||||||
|
|
||||||
|
for collection_id in diff:
|
||||||
|
collection = {"collection_name": collection_id}
|
||||||
|
if diff[collection_id] in [
|
||||||
|
"unmodified", "modified", "created", "deleted"]:
|
||||||
|
collection['buffer_status'] = diff[collection_id]
|
||||||
|
if diff[collection_id] == "created":
|
||||||
|
collection['committed_status'] = 'not present'
|
||||||
|
else:
|
||||||
|
collection['committed_status'] = 'present'
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise AppError(
|
||||||
|
title='Invalid collection status',
|
||||||
|
description=(
|
||||||
|
'Collection_id, {} has an invalid collection status. '
|
||||||
|
'unmodified, modified, created, and deleted are the'
|
||||||
|
' only valid collection statuses.',
|
||||||
|
collection_id),
|
||||||
|
status=falcon.HTTP_500,
|
||||||
|
retry=False, )
|
||||||
|
configdocs_status.append(collection)
|
||||||
|
|
||||||
|
return configdocs_status
|
||||||
|
|
||||||
def _get_revision_dict(self):
|
def _get_revision_dict(self):
|
||||||
"""
|
"""
|
||||||
Returns a dictionary with values representing the revisions in
|
Returns a dictionary with values representing the revisions in
|
||||||
@ -209,13 +246,9 @@ class ConfigdocsHelper(object):
|
|||||||
title='Unable to retrieve revisions',
|
title='Unable to retrieve revisions',
|
||||||
description=(
|
description=(
|
||||||
'Deckhand has responded unexpectedly: {}:{}'.format(
|
'Deckhand has responded unexpectedly: {}:{}'.format(
|
||||||
drex.status_code,
|
drex.status_code, drex.response_message)),
|
||||||
drex.response_message
|
|
||||||
)
|
|
||||||
),
|
|
||||||
status=falcon.HTTP_500,
|
status=falcon.HTTP_500,
|
||||||
retry=False,
|
retry=False)
|
||||||
)
|
|
||||||
self.revision_dict = {
|
self.revision_dict = {
|
||||||
COMMITTED: committed_revision,
|
COMMITTED: committed_revision,
|
||||||
BUFFER: buffer_revision,
|
BUFFER: buffer_revision,
|
||||||
@ -277,16 +310,13 @@ class ConfigdocsHelper(object):
|
|||||||
# revision exists
|
# revision exists
|
||||||
buffer_id = self._get_buffer_rev_id()
|
buffer_id = self._get_buffer_rev_id()
|
||||||
return self.deckhand.get_docs_from_revision(
|
return self.deckhand.get_docs_from_revision(
|
||||||
revision_id=buffer_id,
|
revision_id=buffer_id, bucket_id=collection_id)
|
||||||
bucket_id=collection_id
|
|
||||||
)
|
|
||||||
raise ApiError(
|
raise ApiError(
|
||||||
title='No documents to retrieve',
|
title='No documents to retrieve',
|
||||||
description=('The Shipyard buffer is empty or does not contain '
|
description=('The Shipyard buffer is empty or does not contain '
|
||||||
'this collection'),
|
'this collection'),
|
||||||
status=falcon.HTTP_404,
|
status=falcon.HTTP_404,
|
||||||
retry=False,
|
retry=False)
|
||||||
)
|
|
||||||
|
|
||||||
def _get_committed_docs(self, collection_id):
|
def _get_committed_docs(self, collection_id):
|
||||||
"""
|
"""
|
||||||
@ -295,16 +325,13 @@ class ConfigdocsHelper(object):
|
|||||||
committed_id = self._get_committed_rev_id()
|
committed_id = self._get_committed_rev_id()
|
||||||
if committed_id:
|
if committed_id:
|
||||||
return self.deckhand.get_docs_from_revision(
|
return self.deckhand.get_docs_from_revision(
|
||||||
revision_id=committed_id,
|
revision_id=committed_id, bucket_id=collection_id)
|
||||||
bucket_id=collection_id
|
|
||||||
)
|
|
||||||
# if there is no committed...
|
# if there is no committed...
|
||||||
raise ApiError(
|
raise ApiError(
|
||||||
title='No documents to retrieve',
|
title='No documents to retrieve',
|
||||||
description='There is no committed version of this collection',
|
description='There is no committed version of this collection',
|
||||||
status=falcon.HTTP_404,
|
status=falcon.HTTP_404,
|
||||||
retry=False,
|
retry=False)
|
||||||
)
|
|
||||||
|
|
||||||
def get_rendered_configdocs(self, version=BUFFER):
|
def get_rendered_configdocs(self, version=BUFFER):
|
||||||
"""
|
"""
|
||||||
@ -316,15 +343,13 @@ class ConfigdocsHelper(object):
|
|||||||
if revision_dict.get(version):
|
if revision_dict.get(version):
|
||||||
revision_id = revision_dict.get(version).get('id')
|
revision_id = revision_dict.get(version).get('id')
|
||||||
return self.deckhand.get_rendered_docs_from_revision(
|
return self.deckhand.get_rendered_docs_from_revision(
|
||||||
revision_id=revision_id
|
revision_id=revision_id)
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
raise ApiError(
|
raise ApiError(
|
||||||
title='This revision does not exist',
|
title='This revision does not exist',
|
||||||
description='{} version does not exist'.format(version),
|
description='{} version does not exist'.format(version),
|
||||||
status=falcon.HTTP_404,
|
status=falcon.HTTP_404,
|
||||||
retry=False,
|
retry=False)
|
||||||
)
|
|
||||||
|
|
||||||
def get_validations_for_buffer(self):
|
def get_validations_for_buffer(self):
|
||||||
"""
|
"""
|
||||||
@ -338,17 +363,16 @@ class ConfigdocsHelper(object):
|
|||||||
description=('Buffer revision id could not be determined from'
|
description=('Buffer revision id could not be determined from'
|
||||||
'Deckhand'),
|
'Deckhand'),
|
||||||
status=falcon.HTTP_500,
|
status=falcon.HTTP_500,
|
||||||
retry=False,
|
retry=False)
|
||||||
)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_design_reference(revision_id):
|
def _get_design_reference(revision_id):
|
||||||
# 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+{}".format(DeckhandClient.get_path(
|
"href": "deckhand+{}".format(
|
||||||
DeckhandPaths.RENDERED_REVISION_DOCS).format(revision_id)
|
DeckhandClient.get_path(DeckhandPaths.RENDERED_REVISION_DOCS)
|
||||||
),
|
.format(revision_id)),
|
||||||
"type": "application/x-yaml"
|
"type": "application/x-yaml"
|
||||||
}
|
}
|
||||||
return json.dumps(design_reference)
|
return json.dumps(design_reference)
|
||||||
@ -358,16 +382,18 @@ class ConfigdocsHelper(object):
|
|||||||
# returns the list of validation endpoint supported
|
# returns the list of validation endpoint supported
|
||||||
val_ep = '{}/validatedesign'
|
val_ep = '{}/validatedesign'
|
||||||
return [
|
return [
|
||||||
{'name': 'Drydock',
|
{
|
||||||
'url': val_ep.format(get_endpoint(Endpoints.DRYDOCK))},
|
'name': 'Drydock',
|
||||||
{'name': 'Armada',
|
'url': val_ep.format(get_endpoint(Endpoints.DRYDOCK))
|
||||||
'url': val_ep.format(get_endpoint(Endpoints.ARMADA))},
|
},
|
||||||
|
{
|
||||||
|
'name': 'Armada',
|
||||||
|
'url': val_ep.format(get_endpoint(Endpoints.ARMADA))
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_validation_threads(validation_endpoints,
|
def _get_validation_threads(validation_endpoints, revision_id, ctx):
|
||||||
revision_id,
|
|
||||||
ctx):
|
|
||||||
# create a list of validation threads from the endpoints
|
# create a list of validation threads from the endpoints
|
||||||
validation_threads = []
|
validation_threads = []
|
||||||
for endpoint in validation_endpoints:
|
for endpoint in validation_endpoints:
|
||||||
@ -375,9 +401,9 @@ class ConfigdocsHelper(object):
|
|||||||
response = {'response': None}
|
response = {'response': None}
|
||||||
exception = {'exception': None}
|
exception = {'exception': None}
|
||||||
design_ref = ConfigdocsHelper._get_design_reference(revision_id)
|
design_ref = ConfigdocsHelper._get_design_reference(revision_id)
|
||||||
validation_threads.append(
|
validation_threads.append({
|
||||||
{
|
'thread':
|
||||||
'thread': threading.Thread(
|
threading.Thread(
|
||||||
target=ConfigdocsHelper._get_validations_for_component,
|
target=ConfigdocsHelper._get_validations_for_component,
|
||||||
kwargs={
|
kwargs={
|
||||||
'url': endpoint['url'],
|
'url': endpoint['url'],
|
||||||
@ -391,23 +417,17 @@ class ConfigdocsHelper(object):
|
|||||||
'external_ctx': ctx.external_marker,
|
'external_ctx': ctx.external_marker,
|
||||||
'user': ctx.user
|
'user': ctx.user
|
||||||
}
|
}
|
||||||
}
|
}),
|
||||||
),
|
|
||||||
'name': endpoint['name'],
|
'name': endpoint['name'],
|
||||||
'url': endpoint['url'],
|
'url': endpoint['url'],
|
||||||
'response': response,
|
'response': response,
|
||||||
'exception': exception
|
'exception': exception
|
||||||
}
|
})
|
||||||
)
|
|
||||||
return validation_threads
|
return validation_threads
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_validations_for_component(url,
|
def _get_validations_for_component(url, design_reference, response,
|
||||||
design_reference,
|
exception, context_marker, thread_name,
|
||||||
response,
|
|
||||||
exception,
|
|
||||||
context_marker,
|
|
||||||
thread_name,
|
|
||||||
**kwargs):
|
**kwargs):
|
||||||
# Invoke the POST for validation
|
# Invoke the POST for validation
|
||||||
try:
|
try:
|
||||||
@ -417,10 +437,8 @@ class ConfigdocsHelper(object):
|
|||||||
'content-type': 'application/json'
|
'content-type': 'application/json'
|
||||||
}
|
}
|
||||||
|
|
||||||
http_resp = requests.post(url,
|
http_resp = requests.post(
|
||||||
headers=headers,
|
url, headers=headers, data=design_reference, timeout=(5, 30))
|
||||||
data=design_reference,
|
|
||||||
timeout=(5, 30))
|
|
||||||
# 400 response is "valid" failure to validate. > 400 is a problem.
|
# 400 response is "valid" failure to validate. > 400 is a problem.
|
||||||
if http_resp.status_code > 400:
|
if http_resp.status_code > 400:
|
||||||
http_resp.raise_for_status()
|
http_resp.raise_for_status()
|
||||||
@ -433,16 +451,13 @@ class ConfigdocsHelper(object):
|
|||||||
LOG.error(str(ex))
|
LOG.error(str(ex))
|
||||||
response['response'] = {
|
response['response'] = {
|
||||||
'details': {
|
'details': {
|
||||||
'messageList': [
|
'messageList': [{
|
||||||
{
|
|
||||||
'message': unable_str,
|
'message': unable_str,
|
||||||
'error': True
|
'error': True
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
'message': str(ex),
|
'message': str(ex),
|
||||||
'error': True
|
'error': True
|
||||||
}
|
}]
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exception['exception'] = ex
|
exception['exception'] = ex
|
||||||
@ -457,10 +472,8 @@ class ConfigdocsHelper(object):
|
|||||||
resp_msgs = []
|
resp_msgs = []
|
||||||
|
|
||||||
validation_threads = ConfigdocsHelper._get_validation_threads(
|
validation_threads = ConfigdocsHelper._get_validation_threads(
|
||||||
ConfigdocsHelper._get_validation_endpoints(),
|
ConfigdocsHelper._get_validation_endpoints(), revision_id,
|
||||||
revision_id,
|
self.ctx)
|
||||||
self.ctx
|
|
||||||
)
|
|
||||||
# trigger each validation in parallel
|
# trigger each validation in parallel
|
||||||
for validation_thread in validation_threads:
|
for validation_thread in validation_threads:
|
||||||
if validation_thread.get('thread'):
|
if validation_thread.get('thread'):
|
||||||
@ -475,8 +488,8 @@ class ConfigdocsHelper(object):
|
|||||||
th_name = validation_thread.get('name')
|
th_name = validation_thread.get('name')
|
||||||
val_response = validation_thread.get('response',
|
val_response = validation_thread.get('response',
|
||||||
{}).get('response')
|
{}).get('response')
|
||||||
LOG.debug("Validation from: %s response: %s",
|
LOG.debug("Validation from: %s response: %s", th_name,
|
||||||
th_name, str(val_response))
|
str(val_response))
|
||||||
if validation_thread.get('exception', {}).get('exception'):
|
if validation_thread.get('exception', {}).get('exception'):
|
||||||
LOG.error('Invocation of validation by %s has failed', th_name)
|
LOG.error('Invocation of validation by %s has failed', th_name)
|
||||||
# invalid status needs collection of messages
|
# invalid status needs collection of messages
|
||||||
@ -488,21 +501,17 @@ class ConfigdocsHelper(object):
|
|||||||
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': th_name,
|
'name': th_name,
|
||||||
'message': msg.get('message'),
|
'message': msg.get('message'),
|
||||||
'error': True
|
'error': True
|
||||||
}
|
})
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
resp_msgs.append(
|
resp_msgs.append({
|
||||||
{
|
|
||||||
'name': th_name,
|
'name': th_name,
|
||||||
'message': msg.get('message'),
|
'message': msg.get('message'),
|
||||||
'error': False
|
'error': False
|
||||||
}
|
})
|
||||||
)
|
|
||||||
# Deckhand does it differently. Incorporate those validation
|
# Deckhand does it differently. Incorporate those validation
|
||||||
# failures
|
# failures
|
||||||
dh_validations = self._get_deckhand_validations(revision_id)
|
dh_validations = self._get_deckhand_validations(revision_id)
|
||||||
@ -510,9 +519,7 @@ class ConfigdocsHelper(object):
|
|||||||
resp_msgs.extend(dh_validations)
|
resp_msgs.extend(dh_validations)
|
||||||
# return the formatted status response
|
# return the formatted status response
|
||||||
return ConfigdocsHelper._format_validations_to_status(
|
return ConfigdocsHelper._format_validations_to_status(
|
||||||
resp_msgs,
|
resp_msgs, error_count)
|
||||||
error_count
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_deckhand_validation_status(self, revision_id):
|
def get_deckhand_validation_status(self, revision_id):
|
||||||
"""
|
"""
|
||||||
@ -522,9 +529,7 @@ class ConfigdocsHelper(object):
|
|||||||
dh_validations = self._get_deckhand_validations(revision_id)
|
dh_validations = self._get_deckhand_validations(revision_id)
|
||||||
error_count = len(dh_validations)
|
error_count = len(dh_validations)
|
||||||
return ConfigdocsHelper._format_validations_to_status(
|
return ConfigdocsHelper._format_validations_to_status(
|
||||||
dh_validations,
|
dh_validations, error_count)
|
||||||
error_count
|
|
||||||
)
|
|
||||||
|
|
||||||
def _get_deckhand_validations(self, revision_id):
|
def _get_deckhand_validations(self, revision_id):
|
||||||
# Returns any validations that deckhand has on hand for this
|
# Returns any validations that deckhand has on hand for this
|
||||||
@ -535,13 +540,11 @@ class ConfigdocsHelper(object):
|
|||||||
for dh_result in deckhand_val.get('results'):
|
for dh_result in deckhand_val.get('results'):
|
||||||
if dh_result.get('errors'):
|
if dh_result.get('errors'):
|
||||||
for error in dh_result.get('errors'):
|
for error in dh_result.get('errors'):
|
||||||
resp_msgs.append(
|
resp_msgs.append({
|
||||||
{
|
|
||||||
'name': dh_result.get('name'),
|
'name': dh_result.get('name'),
|
||||||
'message': error.get('message'),
|
'message': error.get('message'),
|
||||||
'error': True
|
'error': True
|
||||||
}
|
})
|
||||||
)
|
|
||||||
return resp_msgs
|
return resp_msgs
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -582,8 +585,7 @@ class ConfigdocsHelper(object):
|
|||||||
description=('Buffer revision id could not be determined from'
|
description=('Buffer revision id could not be determined from'
|
||||||
'Deckhand'),
|
'Deckhand'),
|
||||||
status=falcon.HTTP_500,
|
status=falcon.HTTP_500,
|
||||||
retry=False,
|
retry=False)
|
||||||
)
|
|
||||||
self.tag_revision(buffer_rev_id, tag)
|
self.tag_revision(buffer_rev_id, tag)
|
||||||
|
|
||||||
def tag_revision(self, revision_id, tag):
|
def tag_revision(self, revision_id, tag):
|
||||||
@ -607,15 +609,13 @@ class ConfigdocsHelper(object):
|
|||||||
raise ApiError(
|
raise ApiError(
|
||||||
title='Documents may not exist in more than one collection',
|
title='Documents may not exist in more than one collection',
|
||||||
description=deee.response_message,
|
description=deee.response_message,
|
||||||
status=falcon.HTTP_409
|
status=falcon.HTTP_409)
|
||||||
)
|
|
||||||
except DeckhandRejectedInputError as drie:
|
except DeckhandRejectedInputError as drie:
|
||||||
LOG.info('Deckhand has rejected this input because: %s',
|
LOG.info('Deckhand has rejected this input because: %s',
|
||||||
drie.response_message)
|
drie.response_message)
|
||||||
raise ApiError(
|
raise ApiError(
|
||||||
title="Document(s) invalid syntax or otherwise unsuitable",
|
title="Document(s) invalid syntax or otherwise unsuitable",
|
||||||
description=drie.response_message,
|
description=drie.response_message)
|
||||||
)
|
|
||||||
# reset the revision dict so it regenerates.
|
# reset the revision dict so it regenerates.
|
||||||
self.revision_dict = None
|
self.revision_dict = None
|
||||||
return self._get_buffer_rev_id()
|
return self._get_buffer_rev_id()
|
||||||
|
@ -98,6 +98,15 @@ class ShipyardPolicy(object):
|
|||||||
'method': 'POST'
|
'method': 'POST'
|
||||||
}]
|
}]
|
||||||
),
|
),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
'workflow_orchestrator:get_configdocs_status',
|
||||||
|
RULE_ADMIN_REQUIRED,
|
||||||
|
'Retrieve the status of the configdocs',
|
||||||
|
[{
|
||||||
|
'path': '/api/v1.0/configdocs',
|
||||||
|
'method': 'GET'
|
||||||
|
}]
|
||||||
|
),
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
'workflow_orchestrator:create_configdocs',
|
'workflow_orchestrator:create_configdocs',
|
||||||
RULE_ADMIN_REQUIRED,
|
RULE_ADMIN_REQUIRED,
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
""" Tests for the configdocs_api"""
|
""" Tests for the configdocs_api"""
|
||||||
|
import mock
|
||||||
from mock import patch
|
from mock import patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@ -23,13 +24,43 @@ from shipyard_airflow.control.configdocs.configdocs_api import (
|
|||||||
)
|
)
|
||||||
from shipyard_airflow.control.configdocs.configdocs_helper import \
|
from shipyard_airflow.control.configdocs.configdocs_helper import \
|
||||||
ConfigdocsHelper
|
ConfigdocsHelper
|
||||||
|
from shipyard_airflow.control.api_lock import ApiLock
|
||||||
from shipyard_airflow.errors import ApiError
|
from shipyard_airflow.errors import ApiError
|
||||||
from tests.unit.control import common
|
from tests.unit.control import common
|
||||||
|
|
||||||
CTX = ShipyardRequestContext()
|
CTX = ShipyardRequestContext()
|
||||||
|
|
||||||
|
|
||||||
def test__validate_version_parameter():
|
class TestConfigDocsStatusResource():
|
||||||
|
@patch.object(ConfigdocsHelper, 'get_configdocs_status',
|
||||||
|
common.str_responder)
|
||||||
|
def test_on_get(self, api_client):
|
||||||
|
"""Validate the on_get method returns 200 on success"""
|
||||||
|
result = api_client.simulate_get(
|
||||||
|
"/api/v1.0/configdocs", headers=common.AUTH_HEADERS)
|
||||||
|
assert result.status_code == 200
|
||||||
|
assert result.text == common.str_responder()
|
||||||
|
assert result.headers[
|
||||||
|
'content-type'] == 'application/json; charset=UTF-8'
|
||||||
|
|
||||||
|
|
||||||
|
class TestConfigDocsResource():
|
||||||
|
@patch.object(ConfigDocsResource, 'post_collection', common.str_responder)
|
||||||
|
@mock.patch.object(ApiLock, 'release')
|
||||||
|
@mock.patch.object(ApiLock, 'acquire')
|
||||||
|
def test_on_post(self, mock_acquire, mock_release, api_client):
|
||||||
|
result = api_client.simulate_post(
|
||||||
|
"/api/v1.0/configdocs/coll1", headers=common.AUTH_HEADERS)
|
||||||
|
assert result.status_code == 201
|
||||||
|
|
||||||
|
@patch.object(ConfigDocsResource, 'get_collection', common.str_responder)
|
||||||
|
def test_configdocs_on_get(self, api_client):
|
||||||
|
"""Validate the on_get method returns 200 on success"""
|
||||||
|
result = api_client.simulate_get("/api/v1.0/configdocs/coll1",
|
||||||
|
headers=common.AUTH_HEADERS)
|
||||||
|
assert result.status_code == 200
|
||||||
|
|
||||||
|
def test__validate_version_parameter(self):
|
||||||
"""
|
"""
|
||||||
test of the version parameter validation
|
test of the version parameter validation
|
||||||
"""
|
"""
|
||||||
@ -44,18 +75,17 @@ def test__validate_version_parameter():
|
|||||||
# should not raise an exception.
|
# should not raise an exception.
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
def test_get_collection(self):
|
||||||
def test_get_collection():
|
|
||||||
helper = None
|
helper = None
|
||||||
with patch.object(ConfigdocsHelper, 'get_collection_docs') as mock_method:
|
with patch.object(
|
||||||
|
ConfigdocsHelper, 'get_collection_docs') as mock_method:
|
||||||
cdr = ConfigDocsResource()
|
cdr = ConfigDocsResource()
|
||||||
helper = ConfigdocsHelper(CTX)
|
helper = ConfigdocsHelper(CTX)
|
||||||
cdr.get_collection(helper, 'apples')
|
cdr.get_collection(helper, 'apples')
|
||||||
|
|
||||||
mock_method.assert_called_once_with('buffer', 'apples')
|
mock_method.assert_called_once_with('buffer', 'apples')
|
||||||
|
|
||||||
|
def test_post_collection(self):
|
||||||
def test_post_collection():
|
|
||||||
"""
|
"""
|
||||||
Tests the post collection method of the ConfigdocsResource
|
Tests the post collection method of the ConfigdocsResource
|
||||||
"""
|
"""
|
||||||
@ -88,7 +118,8 @@ def test_post_collection():
|
|||||||
document_data=document_data)
|
document_data=document_data)
|
||||||
|
|
||||||
|
|
||||||
def test_commit_configdocs():
|
class TestCommitConfigDocsResource():
|
||||||
|
def test_commit_configdocs(self):
|
||||||
"""
|
"""
|
||||||
Tests the CommitConfigDocsResource method commit_configdocs
|
Tests the CommitConfigDocsResource method commit_configdocs
|
||||||
"""
|
"""
|
||||||
@ -119,8 +150,7 @@ def test_commit_configdocs():
|
|||||||
assert commit_resp['message'] is not None
|
assert commit_resp['message'] is not None
|
||||||
assert commit_resp['status'] == 'Failure'
|
assert commit_resp['status'] == 'Failure'
|
||||||
|
|
||||||
|
def test_commit_configdocs_force(self):
|
||||||
def test_commit_configdocs_force():
|
|
||||||
"""
|
"""
|
||||||
Tests the CommitConfigDocsResource method commit_configdocs
|
Tests the CommitConfigDocsResource method commit_configdocs
|
||||||
"""
|
"""
|
||||||
@ -138,8 +168,7 @@ def test_commit_configdocs_force():
|
|||||||
assert 'FORCED' in commit_resp['message']
|
assert 'FORCED' in commit_resp['message']
|
||||||
assert commit_resp['status'] == 'Failure'
|
assert commit_resp['status'] == 'Failure'
|
||||||
|
|
||||||
|
def test_commit_configdocs_buffer_err(self):
|
||||||
def test_commit_configdocs_buffer_err():
|
|
||||||
"""
|
"""
|
||||||
Tests the CommitConfigDocsResource method commit_configdocs
|
Tests the CommitConfigDocsResource method commit_configdocs
|
||||||
"""
|
"""
|
||||||
@ -150,11 +179,3 @@ def test_commit_configdocs_buffer_err():
|
|||||||
helper.is_buffer_empty = lambda: True
|
helper.is_buffer_empty = lambda: True
|
||||||
helper.get_validations_for_buffer = lambda: {'status': 'Success'}
|
helper.get_validations_for_buffer = lambda: {'status': 'Success'}
|
||||||
ccdr.commit_configdocs(helper, False)
|
ccdr.commit_configdocs(helper, False)
|
||||||
|
|
||||||
|
|
||||||
@patch.object(ConfigDocsResource, 'get_collection', common.str_responder)
|
|
||||||
def test_configdocs_on_get(api_client):
|
|
||||||
"""Validate the on_get method returns 200 on success"""
|
|
||||||
result = api_client.simulate_get("/api/v1.0/configdocs/coll1",
|
|
||||||
headers=common.AUTH_HEADERS)
|
|
||||||
assert result.status_code == 200
|
|
||||||
|
@ -21,88 +21,89 @@ from .fake_response import FakeResponse
|
|||||||
from shipyard_airflow.control.base import ShipyardRequestContext
|
from shipyard_airflow.control.base import ShipyardRequestContext
|
||||||
from shipyard_airflow.control.configdocs import configdocs_helper
|
from shipyard_airflow.control.configdocs import configdocs_helper
|
||||||
from shipyard_airflow.control.configdocs.configdocs_helper import (
|
from shipyard_airflow.control.configdocs.configdocs_helper import (
|
||||||
BufferMode,
|
BufferMode, ConfigdocsHelper)
|
||||||
ConfigdocsHelper
|
|
||||||
)
|
|
||||||
from shipyard_airflow.control.configdocs.deckhand_client import (
|
from shipyard_airflow.control.configdocs.deckhand_client import (
|
||||||
DeckhandClient,
|
DeckhandClient, DeckhandPaths, DeckhandResponseError,
|
||||||
DeckhandPaths,
|
NoRevisionsExistError)
|
||||||
DeckhandResponseError,
|
|
||||||
NoRevisionsExistError
|
|
||||||
)
|
|
||||||
from shipyard_airflow.errors import ApiError, AppError
|
from shipyard_airflow.errors import ApiError, AppError
|
||||||
|
|
||||||
CTX = ShipyardRequestContext()
|
CTX = ShipyardRequestContext()
|
||||||
|
|
||||||
REV_BUFFER_DICT = {
|
REV_BUFFER_DICT = {
|
||||||
'committed': {'id': 3,
|
'committed': {
|
||||||
|
'id': 3,
|
||||||
'url': 'url3',
|
'url': 'url3',
|
||||||
'createdAt': '2017-07-14T21:23Z',
|
'createdAt': '2017-07-14T21:23Z',
|
||||||
'buckets': ['mop', 'slop'],
|
'buckets': ['mop', 'slop'],
|
||||||
'tags': ['committed'],
|
'tags': ['committed'],
|
||||||
'validationPolicies': {}},
|
'validationPolicies': {}
|
||||||
'buffer': {'id': 5,
|
},
|
||||||
|
'buffer': {
|
||||||
|
'id': 5,
|
||||||
'url': 'url5',
|
'url': 'url5',
|
||||||
'createdAt': '2017-07-16T21:23Z',
|
'createdAt': '2017-07-16T21:23Z',
|
||||||
'buckets': ['mop', 'chum'],
|
'buckets': ['mop', 'chum'],
|
||||||
'tags': ['deckhand_sez_hi'],
|
'tags': ['deckhand_sez_hi'],
|
||||||
'validationPolicies': {}},
|
'validationPolicies': {}
|
||||||
'latest': {'id': 5,
|
},
|
||||||
|
'latest': {
|
||||||
|
'id': 5,
|
||||||
'url': 'url5',
|
'url': 'url5',
|
||||||
'createdAt': '2017-07-16T21:23Z',
|
'createdAt': '2017-07-16T21:23Z',
|
||||||
'buckets': ['mop', 'chum'],
|
'buckets': ['mop', 'chum'],
|
||||||
'tags': ['deckhand_sez_hi'],
|
'tags': ['deckhand_sez_hi'],
|
||||||
'validationPolicies': {}},
|
'validationPolicies': {}
|
||||||
|
},
|
||||||
'revision_count': 5
|
'revision_count': 5
|
||||||
}
|
}
|
||||||
|
|
||||||
DIFF_BUFFER_DICT = {
|
DIFF_BUFFER_DICT = {'mop': 'unmodified', 'chum': 'created', 'slop': 'deleted'}
|
||||||
'mop': 'unmodified',
|
|
||||||
'chum': 'created',
|
|
||||||
'slop': 'deleted'
|
|
||||||
}
|
|
||||||
|
|
||||||
REV_BUFF_EMPTY_DICT = {
|
REV_BUFF_EMPTY_DICT = {
|
||||||
'committed': {'id': 3,
|
'committed': {
|
||||||
|
'id': 3,
|
||||||
'url': 'url3',
|
'url': 'url3',
|
||||||
'createdAt': '2017-07-14T21:23Z',
|
'createdAt': '2017-07-14T21:23Z',
|
||||||
'buckets': ['mop'],
|
'buckets': ['mop'],
|
||||||
'tags': ['committed'],
|
'tags': ['committed'],
|
||||||
'validationPolicies': {}},
|
'validationPolicies': {}
|
||||||
|
},
|
||||||
'buffer': None,
|
'buffer': None,
|
||||||
'latest': {'id': 3,
|
'latest': {
|
||||||
|
'id': 3,
|
||||||
'url': 'url3',
|
'url': 'url3',
|
||||||
'createdAt': '2017-07-14T21:23Z',
|
'createdAt': '2017-07-14T21:23Z',
|
||||||
'buckets': ['mop'],
|
'buckets': ['mop'],
|
||||||
'tags': ['committed'],
|
'tags': ['committed'],
|
||||||
'validationPolicies': {}},
|
'validationPolicies': {}
|
||||||
|
},
|
||||||
'revision_count': 3
|
'revision_count': 3
|
||||||
}
|
}
|
||||||
|
|
||||||
DIFF_BUFF_EMPTY_DICT = {
|
DIFF_BUFF_EMPTY_DICT = {'mop': 'unmodified'}
|
||||||
'mop': 'unmodified'
|
|
||||||
}
|
|
||||||
|
|
||||||
REV_NO_COMMIT_DICT = {
|
REV_NO_COMMIT_DICT = {
|
||||||
'committed': None,
|
'committed': None,
|
||||||
'buffer': {'id': 3,
|
'buffer': {
|
||||||
|
'id': 3,
|
||||||
'url': 'url3',
|
'url': 'url3',
|
||||||
'createdAt': '2017-07-14T21:23Z',
|
'createdAt': '2017-07-14T21:23Z',
|
||||||
'buckets': ['mop'],
|
'buckets': ['mop'],
|
||||||
'tags': [],
|
'tags': [],
|
||||||
'validationPolicies': {}},
|
'validationPolicies': {}
|
||||||
'latest': {'id': 3,
|
},
|
||||||
|
'latest': {
|
||||||
|
'id': 3,
|
||||||
'url': 'url3',
|
'url': 'url3',
|
||||||
'createdAt': '2017-07-14T21:23Z',
|
'createdAt': '2017-07-14T21:23Z',
|
||||||
'buckets': ['mop'],
|
'buckets': ['mop'],
|
||||||
'tags': [],
|
'tags': [],
|
||||||
'validationPolicies': {}},
|
'validationPolicies': {}
|
||||||
|
},
|
||||||
'revision_count': 3
|
'revision_count': 3
|
||||||
}
|
}
|
||||||
|
|
||||||
DIFF_NO_COMMIT_DICT = {
|
DIFF_NO_COMMIT_DICT = {'mop': 'created'}
|
||||||
'mop': 'created'
|
|
||||||
}
|
|
||||||
|
|
||||||
REV_EMPTY_DICT = {
|
REV_EMPTY_DICT = {
|
||||||
'committed': None,
|
'committed': None,
|
||||||
@ -114,30 +115,34 @@ REV_EMPTY_DICT = {
|
|||||||
DIFF_EMPTY_DICT = {}
|
DIFF_EMPTY_DICT = {}
|
||||||
|
|
||||||
REV_COMMIT_AND_BUFFER_DICT = {
|
REV_COMMIT_AND_BUFFER_DICT = {
|
||||||
'committed': {'id': 1,
|
'committed': {
|
||||||
|
'id': 1,
|
||||||
'url': 'url3',
|
'url': 'url3',
|
||||||
'createdAt': '2017-07-14T21:23Z',
|
'createdAt': '2017-07-14T21:23Z',
|
||||||
'buckets': ['mop'],
|
'buckets': ['mop'],
|
||||||
'tags': ['committed'],
|
'tags': ['committed'],
|
||||||
'validationPolicies': {}},
|
'validationPolicies': {}
|
||||||
'buffer': {'id': 3,
|
},
|
||||||
|
'buffer': {
|
||||||
|
'id': 3,
|
||||||
'url': 'url3',
|
'url': 'url3',
|
||||||
'createdAt': '2017-07-14T21:23Z',
|
'createdAt': '2017-07-14T21:23Z',
|
||||||
'buckets': ['mop'],
|
'buckets': ['mop'],
|
||||||
'tags': [],
|
'tags': [],
|
||||||
'validationPolicies': {}},
|
'validationPolicies': {}
|
||||||
'latest': {'id': 3,
|
},
|
||||||
|
'latest': {
|
||||||
|
'id': 3,
|
||||||
'url': 'url3',
|
'url': 'url3',
|
||||||
'createdAt': '2017-07-14T21:23Z',
|
'createdAt': '2017-07-14T21:23Z',
|
||||||
'buckets': ['mop'],
|
'buckets': ['mop'],
|
||||||
'tags': [],
|
'tags': [],
|
||||||
'validationPolicies': {}},
|
'validationPolicies': {}
|
||||||
|
},
|
||||||
'revision_count': 3
|
'revision_count': 3
|
||||||
}
|
}
|
||||||
|
|
||||||
DIFF_COMMIT_AND_BUFFER_DICT = {
|
DIFF_COMMIT_AND_BUFFER_DICT = {'mop': 'modified'}
|
||||||
'mop': 'modified'
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def test_construct_configdocs_helper():
|
def test_construct_configdocs_helper():
|
||||||
@ -154,33 +159,22 @@ def test_get_buffer_mode():
|
|||||||
ensures that strings passed to get_buffer_mode are properly handled
|
ensures that strings passed to get_buffer_mode are properly handled
|
||||||
"""
|
"""
|
||||||
# None cases
|
# None cases
|
||||||
|
assert ConfigdocsHelper.get_buffer_mode('') == BufferMode.REJECTONCONTENTS
|
||||||
assert ConfigdocsHelper.get_buffer_mode(
|
assert ConfigdocsHelper.get_buffer_mode(
|
||||||
''
|
None) == BufferMode.REJECTONCONTENTS
|
||||||
) == BufferMode.REJECTONCONTENTS
|
|
||||||
assert ConfigdocsHelper.get_buffer_mode(
|
|
||||||
None
|
|
||||||
) == BufferMode.REJECTONCONTENTS
|
|
||||||
|
|
||||||
# valid cases
|
# valid cases
|
||||||
assert ConfigdocsHelper.get_buffer_mode(
|
assert ConfigdocsHelper.get_buffer_mode(
|
||||||
'rejectoncontents'
|
'rejectoncontents') == BufferMode.REJECTONCONTENTS
|
||||||
) == BufferMode.REJECTONCONTENTS
|
assert ConfigdocsHelper.get_buffer_mode('append') == BufferMode.APPEND
|
||||||
assert ConfigdocsHelper.get_buffer_mode(
|
assert ConfigdocsHelper.get_buffer_mode('replace') == BufferMode.REPLACE
|
||||||
'append'
|
|
||||||
) == BufferMode.APPEND
|
|
||||||
assert ConfigdocsHelper.get_buffer_mode(
|
|
||||||
'replace'
|
|
||||||
) == BufferMode.REPLACE
|
|
||||||
|
|
||||||
# case insensitive
|
# case insensitive
|
||||||
assert ConfigdocsHelper.get_buffer_mode(
|
assert ConfigdocsHelper.get_buffer_mode(
|
||||||
'ReJEcTOnConTenTs'
|
'ReJEcTOnConTenTs') == BufferMode.REJECTONCONTENTS
|
||||||
) == BufferMode.REJECTONCONTENTS
|
|
||||||
|
|
||||||
# bad value
|
# bad value
|
||||||
assert ConfigdocsHelper.get_buffer_mode(
|
assert ConfigdocsHelper.get_buffer_mode('hippopotomus') is None
|
||||||
'hippopotomus'
|
|
||||||
) is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_is_buffer_emtpy():
|
def test_is_buffer_emtpy():
|
||||||
@ -208,8 +202,7 @@ def test_is_collection_in_buffer():
|
|||||||
helper = ConfigdocsHelper(CTX)
|
helper = ConfigdocsHelper(CTX)
|
||||||
helper._get_revision_dict = lambda: REV_BUFFER_DICT
|
helper._get_revision_dict = lambda: REV_BUFFER_DICT
|
||||||
helper.deckhand.get_diff = (
|
helper.deckhand.get_diff = (
|
||||||
lambda old_revision_id, new_revision_id: DIFF_BUFFER_DICT
|
lambda old_revision_id, new_revision_id: DIFF_BUFFER_DICT)
|
||||||
)
|
|
||||||
# mop is not in buffer; chum and slop are in buffer.
|
# mop is not in buffer; chum and slop are in buffer.
|
||||||
# unmodified means it is not in buffer
|
# unmodified means it is not in buffer
|
||||||
assert not helper.is_collection_in_buffer('mop')
|
assert not helper.is_collection_in_buffer('mop')
|
||||||
@ -220,9 +213,7 @@ def test_is_collection_in_buffer():
|
|||||||
|
|
||||||
def _raise_dre():
|
def _raise_dre():
|
||||||
raise DeckhandResponseError(
|
raise DeckhandResponseError(
|
||||||
status_code=9000,
|
status_code=9000, response_message='This is bogus')
|
||||||
response_message='This is bogus'
|
|
||||||
)
|
|
||||||
|
|
||||||
helper._get_revision_dict = _raise_dre
|
helper._get_revision_dict = _raise_dre
|
||||||
|
|
||||||
@ -242,8 +233,7 @@ def test_is_buffer_valid_for_bucket():
|
|||||||
helper = ConfigdocsHelper(CTX)
|
helper = ConfigdocsHelper(CTX)
|
||||||
helper._get_revision_dict = lambda: REV_BUFFER_DICT
|
helper._get_revision_dict = lambda: REV_BUFFER_DICT
|
||||||
helper.deckhand.get_diff = (
|
helper.deckhand.get_diff = (
|
||||||
lambda old_revision_id, new_revision_id: DIFF_BUFFER_DICT
|
lambda old_revision_id, new_revision_id: DIFF_BUFFER_DICT)
|
||||||
)
|
|
||||||
helper.deckhand.rollback = lambda target_revision_id: (
|
helper.deckhand.rollback = lambda target_revision_id: (
|
||||||
set_revision_dict(helper, REV_BUFF_EMPTY_DICT, DIFF_BUFF_EMPTY_DICT)
|
set_revision_dict(helper, REV_BUFF_EMPTY_DICT, DIFF_BUFF_EMPTY_DICT)
|
||||||
)
|
)
|
||||||
@ -279,8 +269,7 @@ def test_is_buffer_valid_for_bucket():
|
|||||||
# set up as if there is no committed revision yet
|
# set up as if there is no committed revision yet
|
||||||
helper._get_revision_dict = lambda: REV_NO_COMMIT_DICT
|
helper._get_revision_dict = lambda: REV_NO_COMMIT_DICT
|
||||||
helper.deckhand.get_diff = (
|
helper.deckhand.get_diff = (
|
||||||
lambda old_revision_id, new_revision_id: DIFF_NO_COMMIT_DICT
|
lambda old_revision_id, new_revision_id: DIFF_NO_COMMIT_DICT)
|
||||||
)
|
|
||||||
|
|
||||||
assert helper.is_buffer_valid_for_bucket('slop', BufferMode.APPEND)
|
assert helper.is_buffer_valid_for_bucket('slop', BufferMode.APPEND)
|
||||||
assert helper.is_buffer_valid_for_bucket('chum', BufferMode.APPEND)
|
assert helper.is_buffer_valid_for_bucket('chum', BufferMode.APPEND)
|
||||||
@ -295,8 +284,7 @@ def test_is_buffer_valid_for_bucket():
|
|||||||
# set up as if there is nothing in deckhand.
|
# set up as if there is nothing in deckhand.
|
||||||
helper._get_revision_dict = lambda: REV_EMPTY_DICT
|
helper._get_revision_dict = lambda: REV_EMPTY_DICT
|
||||||
helper.deckhand.get_diff = (
|
helper.deckhand.get_diff = (
|
||||||
lambda old_revision_id, new_revision_id: DIFF_EMPTY_DICT
|
lambda old_revision_id, new_revision_id: DIFF_EMPTY_DICT)
|
||||||
)
|
|
||||||
# should be able to add in any mode.
|
# should be able to add in any mode.
|
||||||
assert helper.is_buffer_valid_for_bucket('slop', BufferMode.APPEND)
|
assert helper.is_buffer_valid_for_bucket('slop', BufferMode.APPEND)
|
||||||
assert helper.is_buffer_valid_for_bucket('chum', BufferMode.APPEND)
|
assert helper.is_buffer_valid_for_bucket('chum', BufferMode.APPEND)
|
||||||
@ -305,6 +293,30 @@ def test_is_buffer_valid_for_bucket():
|
|||||||
assert helper.is_buffer_valid_for_bucket('mop', BufferMode.REPLACE)
|
assert helper.is_buffer_valid_for_bucket('mop', BufferMode.REPLACE)
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_configdocs_status():
|
||||||
|
helper = ConfigdocsHelper(CTX)
|
||||||
|
helper._get_revision_dict = lambda: REV_BUFFER_DICT
|
||||||
|
helper.deckhand.get_diff = (
|
||||||
|
lambda old_revision_id, new_revision_id: DIFF_BUFFER_DICT)
|
||||||
|
result = helper.get_configdocs_status()
|
||||||
|
|
||||||
|
expected = [{
|
||||||
|
"collection_name": 'chum',
|
||||||
|
"committed_status": 'not present',
|
||||||
|
"buffer_status": 'created'
|
||||||
|
}, {
|
||||||
|
"collection_name": 'mop',
|
||||||
|
"committed_status": 'present',
|
||||||
|
"buffer_status": 'unmodified'
|
||||||
|
}, {
|
||||||
|
"collection_name": 'slop',
|
||||||
|
"committed_status": 'present',
|
||||||
|
"buffer_status": 'deleted'
|
||||||
|
}]
|
||||||
|
|
||||||
|
assert expected == sorted(result, key=lambda x: x['collection_name'])
|
||||||
|
|
||||||
|
|
||||||
def test__get_revision_dict_no_commit():
|
def test__get_revision_dict_no_commit():
|
||||||
"""
|
"""
|
||||||
Tests the processing of revision dict response from dechand
|
Tests the processing of revision dict response from dechand
|
||||||
@ -439,11 +451,10 @@ def test__get_revision_dict_errs():
|
|||||||
tests getting a revision dictionary method when the deckhand
|
tests getting a revision dictionary method when the deckhand
|
||||||
client has raised an exception
|
client has raised an exception
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _raise_dre():
|
def _raise_dre():
|
||||||
raise DeckhandResponseError(
|
raise DeckhandResponseError(
|
||||||
status_code=9000,
|
status_code=9000, response_message='This is bogus')
|
||||||
response_message='This is bogus'
|
|
||||||
)
|
|
||||||
|
|
||||||
def _raise_nree():
|
def _raise_nree():
|
||||||
raise NoRevisionsExistError()
|
raise NoRevisionsExistError()
|
||||||
@ -472,12 +483,10 @@ def test_get_collection_docs():
|
|||||||
"""
|
"""
|
||||||
helper = ConfigdocsHelper(CTX)
|
helper = ConfigdocsHelper(CTX)
|
||||||
helper.deckhand.get_docs_from_revision = (
|
helper.deckhand.get_docs_from_revision = (
|
||||||
lambda revision_id, bucket_id: "{'yaml': 'yaml'}"
|
lambda revision_id, bucket_id: "{'yaml': 'yaml'}")
|
||||||
)
|
|
||||||
helper._get_revision_dict = lambda: REV_EMPTY_DICT
|
helper._get_revision_dict = lambda: REV_EMPTY_DICT
|
||||||
helper.deckhand.get_diff = (
|
helper.deckhand.get_diff = (
|
||||||
lambda old_revision_id, new_revision_id: DIFF_EMPTY_DICT
|
lambda old_revision_id, new_revision_id: DIFF_EMPTY_DICT)
|
||||||
)
|
|
||||||
|
|
||||||
with pytest.raises(ApiError):
|
with pytest.raises(ApiError):
|
||||||
helper.get_collection_docs(configdocs_helper.BUFFER, 'mop')
|
helper.get_collection_docs(configdocs_helper.BUFFER, 'mop')
|
||||||
@ -487,31 +496,30 @@ def test_get_collection_docs():
|
|||||||
|
|
||||||
helper._get_revision_dict = lambda: REV_COMMIT_AND_BUFFER_DICT
|
helper._get_revision_dict = lambda: REV_COMMIT_AND_BUFFER_DICT
|
||||||
helper.deckhand.get_diff = (
|
helper.deckhand.get_diff = (
|
||||||
lambda old_revision_id, new_revision_id: DIFF_COMMIT_AND_BUFFER_DICT
|
lambda old_revision_id, new_revision_id: DIFF_COMMIT_AND_BUFFER_DICT)
|
||||||
)
|
|
||||||
yaml_str = helper.get_collection_docs(configdocs_helper.BUFFER, 'mop')
|
yaml_str = helper.get_collection_docs(configdocs_helper.BUFFER, 'mop')
|
||||||
print(yaml_str)
|
|
||||||
assert len(yaml_str) == 16
|
assert len(yaml_str) == 16
|
||||||
|
|
||||||
yaml_str = helper.get_collection_docs(configdocs_helper.COMMITTED, 'mop')
|
yaml_str = helper.get_collection_docs(configdocs_helper.COMMITTED, 'mop')
|
||||||
print(yaml_str)
|
|
||||||
assert len(yaml_str) == 16
|
assert len(yaml_str) == 16
|
||||||
|
|
||||||
|
|
||||||
def _fake_get_validation_endpoints():
|
def _fake_get_validation_endpoints():
|
||||||
val_ep = '{}/validatedesign'
|
val_ep = '{}/validatedesign'
|
||||||
return [
|
return [
|
||||||
{'name': 'Drydock', 'url': val_ep.format('drydock')},
|
{
|
||||||
{'name': 'Armada', 'url': val_ep.format('armada')},
|
'name': 'Drydock',
|
||||||
|
'url': val_ep.format('drydock')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'Armada',
|
||||||
|
'url': val_ep.format('armada')
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def _fake_get_validations_for_component(url,
|
def _fake_get_validations_for_component(url, design_reference, response,
|
||||||
design_reference,
|
exception, context_marker, **kwargs):
|
||||||
response,
|
|
||||||
exception,
|
|
||||||
context_marker,
|
|
||||||
**kwargs):
|
|
||||||
"""
|
"""
|
||||||
Responds with a status response
|
Responds with a status response
|
||||||
"""
|
"""
|
||||||
@ -547,11 +555,9 @@ def test_get_validations_for_revision():
|
|||||||
hold_ve = helper.__class__._get_validation_endpoints
|
hold_ve = helper.__class__._get_validation_endpoints
|
||||||
hold_vfc = helper.__class__._get_validations_for_component
|
hold_vfc = helper.__class__._get_validations_for_component
|
||||||
helper.__class__._get_validation_endpoints = (
|
helper.__class__._get_validation_endpoints = (
|
||||||
_fake_get_validation_endpoints
|
_fake_get_validation_endpoints)
|
||||||
)
|
|
||||||
helper.__class__._get_validations_for_component = (
|
helper.__class__._get_validations_for_component = (
|
||||||
_fake_get_validations_for_component
|
_fake_get_validations_for_component)
|
||||||
)
|
|
||||||
helper._get_deckhand_validations = lambda revision_id: []
|
helper._get_deckhand_validations = lambda revision_id: []
|
||||||
try:
|
try:
|
||||||
val_status = helper.get_validations_for_revision(3)
|
val_status = helper.get_validations_for_revision(3)
|
||||||
@ -565,7 +571,9 @@ def test_get_validations_for_revision():
|
|||||||
mock_get_path.assert_called_with(DeckhandPaths.RENDERED_REVISION_DOCS)
|
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="""
|
||||||
---
|
---
|
||||||
count: 2
|
count: 2
|
||||||
next: null
|
next: null
|
||||||
@ -580,7 +588,9 @@ results:
|
|||||||
...
|
...
|
||||||
""")
|
""")
|
||||||
|
|
||||||
FK_VAL_SUBSET_RESP = FakeResponse(status_code=200, text="""
|
FK_VAL_SUBSET_RESP = FakeResponse(
|
||||||
|
status_code=200,
|
||||||
|
text="""
|
||||||
---
|
---
|
||||||
count: 1
|
count: 1
|
||||||
next: null
|
next: null
|
||||||
@ -592,8 +602,9 @@ results:
|
|||||||
...
|
...
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
FK_VAL_ENTRY_RESP = FakeResponse(
|
||||||
FK_VAL_ENTRY_RESP = FakeResponse(status_code=200, text="""
|
status_code=200,
|
||||||
|
text="""
|
||||||
---
|
---
|
||||||
name: promenade-site-validation
|
name: promenade-site-validation
|
||||||
url: https://deckhand/a/url/too/long/for/pep8
|
url: https://deckhand/a/url/too/long/for/pep8
|
||||||
@ -618,14 +629,11 @@ def test__get_deckhand_validations():
|
|||||||
"""
|
"""
|
||||||
helper = ConfigdocsHelper(CTX)
|
helper = ConfigdocsHelper(CTX)
|
||||||
helper.deckhand._get_base_validation_resp = (
|
helper.deckhand._get_base_validation_resp = (
|
||||||
lambda revision_id: FK_VAL_BASE_RESP
|
lambda revision_id: FK_VAL_BASE_RESP)
|
||||||
)
|
|
||||||
helper.deckhand._get_subset_validation_response = (
|
helper.deckhand._get_subset_validation_response = (
|
||||||
lambda reivsion_id, subset_name: FK_VAL_SUBSET_RESP
|
lambda reivsion_id, subset_name: FK_VAL_SUBSET_RESP)
|
||||||
)
|
|
||||||
helper.deckhand._get_entry_validation_response = (
|
helper.deckhand._get_entry_validation_response = (
|
||||||
lambda reivsion_id, subset_name, entry_id: FK_VAL_ENTRY_RESP
|
lambda reivsion_id, subset_name, entry_id: FK_VAL_ENTRY_RESP)
|
||||||
)
|
|
||||||
assert len(helper._get_deckhand_validations(5)) == 2
|
assert len(helper._get_deckhand_validations(5)) == 2
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user