Fix abstract parent documents substitutions not propagating

This is to fix abstract parent documents that have registered
substitutions but are not propagating those substitutions
down to concrete children that rely on that substituted data
(whereas it is irrelevant to the end user whether the abstract
parent receives those substitutions or not).

After this change abstract documents will always undergo
substitution such that their concrete children documents should
inherit those changes.

A unit test has been added for regression.

Change-Id: I73ed8d4caa6923492cc5ff042ecc57fbfeeb7c1c
This commit is contained in:
Felipe Monteiro 2018-03-06 18:03:43 -05:00
parent 3cdf3d2d89
commit fbfb9e79af
2 changed files with 45 additions and 4 deletions

View File

@ -483,16 +483,20 @@ class DocumentLayering(object):
self._documents_by_index[(doc.schema, doc.name)] = (
rendered_data)
# Update the actual document data if concrete.
if not doc.is_abstract:
# Perform substitutions on abstract data for child documents that
# inherit from it, but only update the document's data if concrete.
if doc.substitutions:
substituted_data = list(
self.secrets_substitution.substitute_all(doc))
if substituted_data:
rendered_data = substituted_data[0]
doc.data = rendered_data.data
# Update the actual document data if concrete.
if not doc.is_abstract:
doc.data = rendered_data.data
self.secrets_substitution.update_substitution_sources(
doc.schema, doc.name, rendered_data.data)
self._documents_by_index[(doc.schema, doc.name)] = doc
self._documents_by_index[(doc.schema, doc.name)] = (
rendered_data)
# Return only concrete documents.
return [d for d in self._sorted_documents if d.is_abstract is False]

View File

@ -676,3 +676,40 @@ class TestDocumentLayeringWithSubstitution(
global_expected=global_expected,
substitution_sources=[
certificate, certificate_key] + documents)
def test_layering_and_substitution_site_abstract_and_global_concrete(self):
"""Verifies that if a global document is abstract, yet has
substitutions, those substitutions are performed and carry down to
concrete children that inherit from the abstract parent.
"""
secrets_factory = factories.DocumentSecretFactory()
certificate = secrets_factory.gen_test(
'Certificate', 'cleartext', data='global-secret',
name='global-cert')
mapping = {
"_GLOBAL_DATA_1_": {"data": {"global": "random"}},
"_GLOBAL_SUBSTITUTIONS_1_": [{
"dest": {
"path": ".cert"
},
"src": {
"schema": certificate['schema'],
"name": certificate['metadata']['name'],
"path": "."
}
}],
"_SITE_DATA_1_": {"data": {"site": "stuff"}},
"_SITE_ACTIONS_1_": {
"actions": [{"method": "merge", "path": "."}]}
}
doc_factory = factories.DocumentFactory(2, [1, 1])
documents = doc_factory.gen_test(mapping, site_abstract=False,
global_abstract=True)
site_expected = {"global": "random", "cert": "global-secret",
"site": "stuff"}
global_expected = None
self._test_layering(documents, site_expected,
global_expected=global_expected,
substitution_sources=[certificate])