Fix Promenade: Introduce flag to only warn on missing sub source
This PS introduces a flag to only warn on missing substitution sources because right now Promenade is failing on that. However, a PS will also have to be added to Promenade to set the new flag -- `fail_on_missing_sub_src` -- to False during genesis. Change-Id: I462f721c41e23d2e5e3e698c0bd452b6764d51eb
This commit is contained in:
parent
3d278a2b08
commit
87d7f94134
@ -265,7 +265,8 @@ class DocumentLayering(object):
|
||||
details='The following pre-validation errors occurred '
|
||||
'(schema, name, error): %s.' % val_errors)
|
||||
|
||||
def __init__(self, documents, substitution_sources=None, validate=True):
|
||||
def __init__(self, documents, substitution_sources=None, validate=True,
|
||||
fail_on_missing_sub_src=True):
|
||||
"""Contructor for ``DocumentLayering``.
|
||||
|
||||
:param layering_policy: The document with schema
|
||||
@ -280,6 +281,9 @@ class DocumentLayering(object):
|
||||
:param validate: Whether to pre-validate documents using built-in
|
||||
schema validation. Default is True.
|
||||
:type validate: bool
|
||||
:param fail_on_missing_sub_src: Whether to fail on a missing
|
||||
substitution source. Default is True.
|
||||
:type fail_on_missing_sub_src: bool
|
||||
|
||||
:raises LayeringPolicyNotFound: If no LayeringPolicy was found among
|
||||
list of ``documents``.
|
||||
@ -349,7 +353,8 @@ class DocumentLayering(object):
|
||||
self._calc_all_document_children()
|
||||
self._substitution_sources = substitution_sources or []
|
||||
self.secrets_substitution = secrets_manager.SecretsSubstitution(
|
||||
self._substitution_sources)
|
||||
self._substitution_sources,
|
||||
fail_on_missing_sub_src=fail_on_missing_sub_src)
|
||||
|
||||
del self._documents_by_layer
|
||||
del self._documents_by_labels
|
||||
|
@ -105,7 +105,8 @@ class SecretsManager(object):
|
||||
class SecretsSubstitution(object):
|
||||
"""Class for document substitution logic for YAML files."""
|
||||
|
||||
def __init__(self, substitution_sources=None):
|
||||
def __init__(self, substitution_sources=None,
|
||||
fail_on_missing_sub_src=True):
|
||||
"""SecretSubstitution constructor.
|
||||
|
||||
This class will automatically detect documents that require
|
||||
@ -115,9 +116,12 @@ class SecretsSubstitution(object):
|
||||
:param substitution_sources: List of documents that are potential
|
||||
sources for substitution. Should only include concrete documents.
|
||||
:type substitution_sources: List[dict]
|
||||
:param bool fail_on_missing_sub_src: Whether to fail on a missing
|
||||
substitution source. Default is True.
|
||||
"""
|
||||
|
||||
self._substitution_sources = {}
|
||||
self._fail_on_missing_sub_src = fail_on_missing_sub_src
|
||||
|
||||
for document in substitution_sources:
|
||||
if not isinstance(document, document_wrapper.DocumentDict):
|
||||
@ -175,11 +179,15 @@ class SecretsSubstitution(object):
|
||||
message = ('Could not find substitution source document '
|
||||
'[%s] %s among the provided '
|
||||
'`substitution_sources`.', src_schema, src_name)
|
||||
LOG.error(message)
|
||||
raise errors.SubstitutionSourceNotFound(
|
||||
src_schema=src_schema, src_name=src_name,
|
||||
document_schema=document.schema,
|
||||
document_name=document.name)
|
||||
if self._fail_on_missing_sub_src:
|
||||
LOG.error(message)
|
||||
raise errors.SubstitutionSourceNotFound(
|
||||
src_schema=src_schema, src_name=src_name,
|
||||
document_schema=document.schema,
|
||||
document_name=document.name)
|
||||
else:
|
||||
LOG.warning(message)
|
||||
continue
|
||||
|
||||
# If the data is a dictionary, retrieve the nested secret
|
||||
# via jsonpath_parse, else the secret is the primitive/string
|
||||
|
@ -14,7 +14,10 @@
|
||||
|
||||
import yaml
|
||||
|
||||
import mock
|
||||
|
||||
from deckhand.engine import layering
|
||||
from deckhand.engine import secrets_manager
|
||||
from deckhand import errors
|
||||
from deckhand import factories
|
||||
from deckhand.tests.unit import base as test_base
|
||||
@ -88,6 +91,34 @@ class TestDocumentLayering(test_base.DeckhandTestCase):
|
||||
self.assertEmpty(global_docs)
|
||||
|
||||
|
||||
class TestDocumentLayeringScenarios(TestDocumentLayering):
|
||||
|
||||
@mock.patch.object(secrets_manager, 'LOG', autospec=True)
|
||||
def test_layering_with_missing_substitution_source_log_warning(self,
|
||||
m_log):
|
||||
"""Validate that a missing substitution source document fails."""
|
||||
mapping = {
|
||||
"_SITE_SUBSTITUTIONS_1_": [{
|
||||
"dest": {
|
||||
"path": ".c"
|
||||
},
|
||||
"src": {
|
||||
"schema": "example/Kind/v1",
|
||||
"name": "nowhere-to-be-found",
|
||||
"path": "."
|
||||
}
|
||||
}]
|
||||
}
|
||||
doc_factory = factories.DocumentFactory(2, [1, 1])
|
||||
documents = doc_factory.gen_test(mapping, site_abstract=False)
|
||||
|
||||
self._test_layering(documents, site_expected={},
|
||||
fail_on_missing_sub_src=False)
|
||||
self.assertTrue(m_log.warning.called)
|
||||
self.assertRegex(m_log.warning.mock_calls[0][1][0][0],
|
||||
r'Could not find substitution source document .*')
|
||||
|
||||
|
||||
class TestDocumentLayering2Layers(TestDocumentLayering):
|
||||
|
||||
def test_layering_default_scenario(self):
|
||||
|
Loading…
Reference in New Issue
Block a user