Merge "refactor: Move replacement checks into separate module"
This commit is contained in:
commit
eb178e1d7f
|
@ -0,0 +1,82 @@
|
||||||
|
# Copyright 2018 AT&T Intellectual Property. All other rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""Functions for validation replacement logic."""
|
||||||
|
from deckhand import errors
|
||||||
|
|
||||||
|
|
||||||
|
def check_document_with_replacement_field_has_parent(
|
||||||
|
parent_meta, parent, document):
|
||||||
|
"""Validate that a document with ``metadata.replacement`` has a parent."""
|
||||||
|
if not parent_meta or not parent:
|
||||||
|
error_message = (
|
||||||
|
'Document replacement requires that the document with '
|
||||||
|
'`replacement: true` have a parent.')
|
||||||
|
raise errors.InvalidDocumentReplacement(
|
||||||
|
schema=document.schema, name=document.name,
|
||||||
|
layer=document.layer, reason=error_message)
|
||||||
|
|
||||||
|
|
||||||
|
def check_replacement_and_parent_same_schema_and_name(
|
||||||
|
parent, document):
|
||||||
|
"""Validate that replacement-child and replacement-parent documents have
|
||||||
|
the same ``schema`` and ``metadata.name`` values which is a hard
|
||||||
|
requirement for replacement.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# This checks that a document can only be a replacement for
|
||||||
|
# another document with the same `metadata.name` and `schema`.
|
||||||
|
if not (document.schema == parent.schema and
|
||||||
|
document.name == parent.name):
|
||||||
|
error_message = (
|
||||||
|
'Document replacement requires that both documents '
|
||||||
|
'have the same `schema` and `metadata.name`.')
|
||||||
|
raise errors.InvalidDocumentReplacement(
|
||||||
|
schema=document.schema, name=document.name,
|
||||||
|
layer=document.layer, reason=error_message)
|
||||||
|
|
||||||
|
|
||||||
|
def check_child_and_parent_different_metadata_name(
|
||||||
|
parent, document):
|
||||||
|
"""Validate that "regular" child and parent documents (without a
|
||||||
|
replacement relationship) have the same ``schema`` but different
|
||||||
|
``metadata.name``.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if (parent and document.schema == parent.schema and
|
||||||
|
document.name == parent.name):
|
||||||
|
error_message = (
|
||||||
|
'Non-replacement documents cannot have the same `schema` '
|
||||||
|
'and `metadata.name` as their parent. Either add '
|
||||||
|
'`replacement: true` to the document or give the document '
|
||||||
|
'a different name.')
|
||||||
|
raise errors.InvalidDocumentReplacement(
|
||||||
|
schema=document.schema, name=document.name,
|
||||||
|
layer=document.layer, reason=error_message)
|
||||||
|
|
||||||
|
|
||||||
|
def check_only_one_level_of_replacement(src_ref):
|
||||||
|
"""Validate that only one level of replacement exists, meaning that
|
||||||
|
a replacement document cannot itself be replaced by yet another
|
||||||
|
replacement document.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# If the document has a replacement, use the replacement as the
|
||||||
|
# substitution source instead.
|
||||||
|
if src_ref.is_replacement:
|
||||||
|
error_message = ('A replacement document cannot itself'
|
||||||
|
' be replaced by another document.')
|
||||||
|
raise errors.InvalidDocumentReplacement(
|
||||||
|
schema=src_ref.schema, name=src_ref.name,
|
||||||
|
layer=src_ref.layer, reason=error_message)
|
|
@ -24,6 +24,7 @@ from oslo_utils import excutils
|
||||||
from deckhand.common.document import DocumentDict as dd
|
from deckhand.common.document import DocumentDict as dd
|
||||||
from deckhand.common import utils
|
from deckhand.common import utils
|
||||||
from deckhand.common.validation_message import ValidationMessage
|
from deckhand.common.validation_message import ValidationMessage
|
||||||
|
from deckhand.engine import _replacement as replacement
|
||||||
from deckhand.engine import document_validation
|
from deckhand.engine import document_validation
|
||||||
from deckhand.engine import secrets_manager
|
from deckhand.engine import secrets_manager
|
||||||
from deckhand.engine import utils as engine_utils
|
from deckhand.engine import utils as engine_utils
|
||||||
|
@ -59,64 +60,18 @@ class DocumentLayering(object):
|
||||||
def _calc_replacements_and_substitutions(
|
def _calc_replacements_and_substitutions(
|
||||||
self, substitution_sources):
|
self, substitution_sources):
|
||||||
|
|
||||||
def _check_document_with_replacement_field_has_parent(
|
|
||||||
parent_meta, parent, document):
|
|
||||||
if not parent_meta or not parent:
|
|
||||||
error_message = (
|
|
||||||
'Document replacement requires that the document with '
|
|
||||||
'`replacement: true` have a parent.')
|
|
||||||
raise errors.InvalidDocumentReplacement(
|
|
||||||
schema=document.schema, name=document.name,
|
|
||||||
layer=document.layer, reason=error_message)
|
|
||||||
|
|
||||||
def _check_replacement_and_parent_same_schema_and_name(
|
|
||||||
parent, document):
|
|
||||||
# This checks that a document can only be a replacement for
|
|
||||||
# another document with the same `metadata.name` and `schema`.
|
|
||||||
if not (document.schema == parent.schema and
|
|
||||||
document.name == parent.name):
|
|
||||||
error_message = (
|
|
||||||
'Document replacement requires that both documents '
|
|
||||||
'have the same `schema` and `metadata.name`.')
|
|
||||||
raise errors.InvalidDocumentReplacement(
|
|
||||||
schema=document.schema, name=document.name,
|
|
||||||
layer=document.layer, reason=error_message)
|
|
||||||
|
|
||||||
def _check_non_replacement_and_parent_different_schema_and_name(
|
|
||||||
parent, document):
|
|
||||||
if (parent and document.schema == parent.schema and
|
|
||||||
document.name == parent.name):
|
|
||||||
error_message = (
|
|
||||||
'Non-replacement documents cannot have the same `schema` '
|
|
||||||
'and `metadata.name` as their parent. Either add '
|
|
||||||
'`replacement: true` to the document or give the document '
|
|
||||||
'a different name.')
|
|
||||||
raise errors.InvalidDocumentReplacement(
|
|
||||||
schema=document.schema, name=document.name,
|
|
||||||
layer=document.layer, reason=error_message)
|
|
||||||
|
|
||||||
def _check_replacement_not_itself_replaced_by_another(src_ref):
|
|
||||||
# If the document has a replacement, use the replacement as the
|
|
||||||
# substitution source instead.
|
|
||||||
if src_ref.is_replacement:
|
|
||||||
error_message = ('A replacement document cannot itself'
|
|
||||||
' be replaced by another document.')
|
|
||||||
raise errors.InvalidDocumentReplacement(
|
|
||||||
schema=src_ref.schema, name=src_ref.name,
|
|
||||||
layer=src_ref.layer, reason=error_message)
|
|
||||||
|
|
||||||
for document in self._documents_by_index.values():
|
for document in self._documents_by_index.values():
|
||||||
parent_meta = self._parents.get(document.meta)
|
parent_meta = self._parents.get(document.meta)
|
||||||
parent = self._documents_by_index.get(parent_meta)
|
parent = self._documents_by_index.get(parent_meta)
|
||||||
|
|
||||||
if document.is_replacement:
|
if document.is_replacement:
|
||||||
_check_document_with_replacement_field_has_parent(
|
replacement.check_document_with_replacement_field_has_parent(
|
||||||
parent_meta, parent, document)
|
parent_meta, parent, document)
|
||||||
_check_replacement_and_parent_same_schema_and_name(
|
replacement.check_replacement_and_parent_same_schema_and_name(
|
||||||
parent, document)
|
parent, document)
|
||||||
parent.replaced_by = document
|
parent.replaced_by = document
|
||||||
else:
|
else:
|
||||||
_check_non_replacement_and_parent_different_schema_and_name(
|
replacement.check_child_and_parent_different_metadata_name(
|
||||||
parent, document)
|
parent, document)
|
||||||
|
|
||||||
# Since a substitution source only provides the document's
|
# Since a substitution source only provides the document's
|
||||||
|
@ -130,7 +85,7 @@ class DocumentLayering(object):
|
||||||
if src_ref.meta in self._documents_by_index:
|
if src_ref.meta in self._documents_by_index:
|
||||||
src_ref = self._documents_by_index[src_ref.meta]
|
src_ref = self._documents_by_index[src_ref.meta]
|
||||||
if src_ref.has_replacement:
|
if src_ref.has_replacement:
|
||||||
_check_replacement_not_itself_replaced_by_another(src_ref)
|
replacement.check_only_one_level_of_replacement(src_ref)
|
||||||
src_ref = src_ref.replaced_by
|
src_ref = src_ref.replaced_by
|
||||||
substitution_source_map[(src_ref.schema, src_ref.name)] = src_ref
|
substitution_source_map[(src_ref.schema, src_ref.name)] = src_ref
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue