コード例 #1
0
def test_copied_object_picked_on_request():
    src = {'tested-key': {'key': 'val'}}
    dst = {}
    cherrypick(src=src, dst=dst, fields=['tested-key'], picker=copy.copy)

    assert dst == {'tested-key': {'key': 'val'}}
    assert dst['tested-key'] == src['tested-key']
    assert dst['tested-key'] is not src['tested-key']

    src['tested-key']['key'] = 'another-val'
    assert dst['tested-key']['key'] == 'val'
コード例 #2
0
def test_exact_object_picked_by_default():
    src = {'tested-key': {'key': 'val'}}
    dst = {}
    cherrypick(src=src, dst=dst, fields=['tested-key'])

    assert dst == {'tested-key': {'key': 'val'}}
    assert dst['tested-key'] == src['tested-key']
    assert dst['tested-key'] is src['tested-key']

    src['tested-key']['key'] = 'replaced-val'
    assert dst['tested-key']['key'] == 'replaced-val'
コード例 #3
0
def test_overrides_existing_keys():
    src = {'ignored-key': 'src-val', 'tested-key': 'src-val'}
    dst = {'ignored-key': 'dst-val', 'tested-key': 'dst-val'}
    cherrypick(src=src, dst=dst, fields=['tested-key'])
    assert dst == {'ignored-key': 'dst-val', 'tested-key': 'src-val'}
コード例 #4
0
def test_fails_on_nonmapping_dst_key():
    src = {'sub': {'ignored-key': 'src-val', 'tested-key': 'src-val'}}
    dst = {'sub': 'scalar-value'}
    with pytest.raises(TypeError):
        cherrypick(src=src, dst=dst, fields=['sub.tested-key'])
コード例 #5
0
def test_ensures_dst_subdicts():
    src = {'sub': {'ignored-key': 'src-val', 'tested-key': 'src-val'}}
    dst = {}
    cherrypick(src=src, dst=dst, fields=['sub.tested-key'])
    assert dst == {'sub': {'tested-key': 'src-val'}}
コード例 #6
0
def test_skips_absent_src_subkeys():
    src = {'sub': {'ignored-key': 'src-val'}}
    dst = {'sub': {'ignored-key': 'dst-val', 'tested-key': 'dst-val'}}
    cherrypick(src=src, dst=dst, fields=['sub.tested-key'])
    assert dst == {'sub': {'ignored-key': 'dst-val', 'tested-key': 'dst-val'}}
コード例 #7
0
def test_adds_absent_dst_keys():
    src = {'ignored-key': 'src-val', 'tested-key': 'src-val'}
    dst = {'ignored-key': 'dst-val'}
    cherrypick(src=src, dst=dst, fields=['tested-key'])
    assert dst == {'ignored-key': 'dst-val', 'tested-key': 'src-val'}
コード例 #8
0
ファイル: diffbase.py プロジェクト: philipp-sontag-by/kopf
    def build(
        self,
        *,
        body: bodies.Body,
        extra_fields: Optional[Iterable[dicts.FieldSpec]] = None,
    ) -> bodies.BodyEssence:
        """
        Extract only the relevant fields for the state comparisons.

        The framework ignores all the system fields (mostly from metadata)
        and the status senza completely. Except for some well-known and useful
        metadata, such as labels and annotations (except for sure garbage).

        A special set of fields can be provided even if they are supposed
        to be removed. This is used, for example, for handlers which react
        to changes in the specific fields in the status stanza,
        while the rest of the status stanza is removed.

        It is generally not a good idea to override this method in custom
        stores, unless a different definition of an object's essence is needed.
        """

        # Always use a copy, so that future changes do not affect the extracted essence.
        essence = cast(Dict[Any, Any], copy.deepcopy(dict(body)))

        # The top-level identifying fields never change, so there is not need to track them.
        if 'apiVersion' in essence:
            del essence['apiVersion']
        if 'kind' in essence:
            del essence['kind']

        # Purge the whole stenzas with system info (extra-fields are restored below).
        if 'metadata' in essence:
            del essence['metadata']
        if 'status' in essence:
            del essence['status']

        # We want some selected metadata to be tracked implicitly.
        dicts.cherrypick(
            src=body,
            dst=essence,
            fields=[
                'metadata.labels',
                'metadata.annotations',  # but not all of them! deleted below.
            ],
            picker=copy.deepcopy)

        # But we do not want all the annotations, only the potentially useful ones.
        # Also exclude the annotations of other Kopf-based operators' storages.
        annotations = essence.get('metadata', {}).get('annotations', {})
        ignored_prefixes = self._detect_marked_prefixes(annotations)
        for annotation in list(annotations):
            if any(
                    annotation.startswith(f'{prefix}/')
                    for prefix in ignored_prefixes):
                del annotations[annotation]
            elif annotation == 'kubectl.kubernetes.io/last-applied-configuration':
                del annotations[annotation]

        # Restore all explicitly whitelisted extra-fields from the original body.
        dicts.cherrypick(src=body,
                         dst=essence,
                         fields=extra_fields,
                         picker=copy.deepcopy)

        self.remove_empty_stanzas(cast(bodies.BodyEssence, essence))
        return cast(bodies.BodyEssence, essence)