Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions diffsync/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def __init__(self):

`self.children[group][unique_id] == DiffElement(...)`
"""
self.models_processed = 0
Comment thread
ubaumann marked this conversation as resolved.

def __len__(self):
"""Total number of DiffElements stored herein."""
Expand Down Expand Up @@ -115,6 +116,13 @@ def summary(self) -> Mapping[Text, int]:
child_summary = child.summary()
for key in summary:
summary[key] += child_summary[key]
summary[DiffSyncActions.SKIP] = (
self.models_processed
- summary[DiffSyncActions.CREATE]
- 2 * summary[DiffSyncActions.UPDATE]
Comment thread
ubaumann marked this conversation as resolved.
- summary[DiffSyncActions.DELETE]
- 2 * summary["no-change"]
)
return summary

def str(self, indent: int = 0):
Expand Down
1 change: 1 addition & 0 deletions diffsync/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,5 @@ class DiffSyncActions: # pylint: disable=too-few-public-methods
CREATE = "create"
UPDATE = "update"
DELETE = "delete"
SKIP = "skip"
NO_CHANGE = None
1 change: 1 addition & 0 deletions diffsync/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def calculate_diffs(self) -> Diff:
self.diff.add(diff_element)

self.logger.info("Diff calculation complete")
self.diff.models_processed = self.models_processed
self.diff.complete()
return self.diff

Expand Down
4 changes: 2 additions & 2 deletions examples/06-ip-prefixes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ From this `diff`, we can check the summary of what would happen.

```py
>>> diff.summary()
{'create': 2, 'update': 1, 'delete': 1, 'no-change': 0}
{'create': 2, 'update': 1, 'delete': 1, 'no-change': 0, 'skip': 0}
```

And, also go into the details. We can see how the `'+'` and + `'-'` represent the actual changes in the target adapter: create, delete or update (when both symbols appear).
Expand Down Expand Up @@ -119,5 +119,5 @@ Now, if we reload the IPAM B, and try to check the difference, we should see no
>>> new_ipam_b.load()
>>> diff = ipam_a.diff_to(new_ipam_b)
>>> diff.summary()
{'create': 0, 'update': 0, 'delete': 0, 'no-change': 3}
{'create': 0, 'update': 0, 'delete': 0, 'no-change': 3, 'skip': 0}
```
2 changes: 2 additions & 0 deletions tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,8 @@ def diff_with_children():
address_element.add_attrs(source={"state": "NC"}, dest={"state": "NC"})
diff.add(address_element)

diff.models_processed = 8

return diff


Expand Down
4 changes: 2 additions & 2 deletions tests/unit/test_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def test_diff_empty():
def test_diff_summary_with_no_diffs():
diff = Diff()

assert diff.summary() == {"create": 0, "update": 0, "delete": 0, "no-change": 0}
assert diff.summary() == {"create": 0, "update": 0, "delete": 0, "no-change": 0, "skip": 0}


def test_diff_str_with_no_diffs():
Expand Down Expand Up @@ -91,7 +91,7 @@ def test_diff_summary_with_diffs(diff_with_children):
# Delete person "Sully"
# Update interface "device1_eth0"
# No change to address "RTP" and device "device1"
assert diff_with_children.summary() == {"create": 1, "update": 1, "delete": 1, "no-change": 2}
assert diff_with_children.summary() == {"create": 1, "update": 1, "delete": 1, "no-change": 2, "skip": 0}


def test_diff_str_with_diffs(diff_with_children):
Expand Down
16 changes: 8 additions & 8 deletions tests/unit/test_diffsync.py
Original file line number Diff line number Diff line change
Expand Up @@ -810,42 +810,42 @@ def test_diffsync_diff_with_skip_unmatched_src_flag(
backend_a, backend_a_with_extra_models, backend_a_minus_some_models
):
diff = backend_a.diff_from(backend_a_with_extra_models)
assert diff.summary() == {"create": 2, "update": 0, "delete": 0, "no-change": 23}
assert diff.summary() == {"create": 2, "update": 0, "delete": 0, "no-change": 23, "skip": 0}

# SKIP_UNMATCHED_SRC should mean that extra models in the src are not flagged for creation in the dest
diff = backend_a.diff_from(backend_a_with_extra_models, flags=DiffSyncFlags.SKIP_UNMATCHED_SRC)
assert diff.summary() == {"create": 0, "update": 0, "delete": 0, "no-change": 23}
assert diff.summary() == {"create": 0, "update": 0, "delete": 0, "no-change": 23, "skip": 2}

# SKIP_UNMATCHED_SRC should NOT mean that extra models in the dst are not flagged for deletion in the src
diff = backend_a.diff_from(backend_a_minus_some_models, flags=DiffSyncFlags.SKIP_UNMATCHED_SRC)
assert diff.summary() == {"create": 0, "update": 0, "delete": 12, "no-change": 11}
assert diff.summary() == {"create": 0, "update": 0, "delete": 12, "no-change": 11, "skip": 0}


def test_diffsync_diff_with_skip_unmatched_dst_flag(
backend_a, backend_a_with_extra_models, backend_a_minus_some_models
):
diff = backend_a.diff_from(backend_a_minus_some_models)
assert diff.summary() == {"create": 0, "update": 0, "delete": 12, "no-change": 11}
assert diff.summary() == {"create": 0, "update": 0, "delete": 12, "no-change": 11, "skip": 0}

# SKIP_UNMATCHED_DST should mean that missing models in the src are not flagged for deletion from the dest
diff = backend_a.diff_from(backend_a_minus_some_models, flags=DiffSyncFlags.SKIP_UNMATCHED_DST)
assert diff.summary() == {"create": 0, "update": 0, "delete": 0, "no-change": 11}
assert diff.summary() == {"create": 0, "update": 0, "delete": 0, "no-change": 11, "skip": 2}

# SKIP_UNMATCHED_DST should NOT mean that extra models in the src are not flagged for creation in the dest
diff = backend_a.diff_from(backend_a_with_extra_models, flags=DiffSyncFlags.SKIP_UNMATCHED_DST)
assert diff.summary() == {"create": 2, "update": 0, "delete": 0, "no-change": 23}
assert diff.summary() == {"create": 2, "update": 0, "delete": 0, "no-change": 23, "skip": 0}


def test_diffsync_diff_with_skip_unmatched_both_flag(
backend_a, backend_a_with_extra_models, backend_a_minus_some_models
):
# SKIP_UNMATCHED_BOTH should mean that extra models in the src are not flagged for creation in the dest
diff = backend_a.diff_from(backend_a_with_extra_models, flags=DiffSyncFlags.SKIP_UNMATCHED_BOTH)
assert diff.summary() == {"create": 0, "update": 0, "delete": 0, "no-change": 23}
assert diff.summary() == {"create": 0, "update": 0, "delete": 0, "no-change": 23, "skip": 2}

# SKIP_UNMATCHED_BOTH should mean that missing models in the src are not flagged for deletion from the dest
diff = backend_a.diff_from(backend_a_minus_some_models, flags=DiffSyncFlags.SKIP_UNMATCHED_BOTH)
assert diff.summary() == {"create": 0, "update": 0, "delete": 0, "no-change": 11}
assert diff.summary() == {"create": 0, "update": 0, "delete": 0, "no-change": 11, "skip": 2}


def test_diffsync_sync_with_skip_unmatched_src_flag(backend_a, backend_a_with_extra_models):
Expand Down
14 changes: 7 additions & 7 deletions tests/unit/test_diffsync_model_flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,20 @@
def test_diffsync_diff_with_skip_unmatched_src_flag_on_models(backend_a, backend_a_with_extra_models):
# Validate that there are 2 extras objects out of the box
diff = backend_a.diff_from(backend_a_with_extra_models)
assert diff.summary() == {"create": 2, "update": 0, "delete": 0, "no-change": 23}
assert diff.summary() == {"create": 2, "update": 0, "delete": 0, "no-change": 23, "skip": 0}

# Check that only 1 object is affected by the flag
backend_a_with_extra_models.get(
backend_a_with_extra_models.site, "lax"
).model_flags |= DiffSyncModelFlags.SKIP_UNMATCHED_SRC
diff = backend_a.diff_from(backend_a_with_extra_models)
assert diff.summary() == {"create": 1, "update": 0, "delete": 0, "no-change": 23}
assert diff.summary() == {"create": 1, "update": 0, "delete": 0, "no-change": 23, "skip": 1}

backend_a_with_extra_models.get(
backend_a_with_extra_models.device, "nyc-spine3"
).model_flags |= DiffSyncModelFlags.SKIP_UNMATCHED_SRC
diff = backend_a.diff_from(backend_a_with_extra_models)
assert diff.summary() == {"create": 0, "update": 0, "delete": 0, "no-change": 23}
assert diff.summary() == {"create": 0, "update": 0, "delete": 0, "no-change": 23, "skip": 2}


def test_diffsync_sync_with_skip_unmatched_src_flag_on_models(backend_a, backend_a_with_extra_models):
Expand All @@ -58,23 +58,23 @@ def test_diffsync_sync_with_skip_unmatched_src_flag_on_models(backend_a, backend
assert "nyc-spine3" not in backend_a.get(backend_a.site, "nyc").devices

diff = backend_a.diff_from(backend_a_with_extra_models)
assert diff.summary() == {"create": 0, "update": 0, "delete": 0, "no-change": 23}
assert diff.summary() == {"create": 0, "update": 0, "delete": 0, "no-change": 23, "skip": 2}


def test_diffsync_diff_with_skip_unmatched_dst_flag_on_models(backend_a, backend_a_minus_some_models):
# Validate that there are 3 extras objects out of the box
diff = backend_a.diff_from(backend_a_minus_some_models)
assert diff.summary() == {"create": 0, "update": 0, "delete": 12, "no-change": 11}
assert diff.summary() == {"create": 0, "update": 0, "delete": 12, "no-change": 11, "skip": 0}

# Check that only the device "rdu-spine1" and its 2 interfaces are affected by the flag
backend_a.get(backend_a.device, "rdu-spine1").model_flags |= DiffSyncModelFlags.SKIP_UNMATCHED_DST
diff = backend_a.diff_from(backend_a_minus_some_models)
assert diff.summary() == {"create": 0, "update": 0, "delete": 9, "no-change": 11}
assert diff.summary() == {"create": 0, "update": 0, "delete": 9, "no-change": 11, "skip": 1}

# Check that only one additional device "sfo-spine2" and its 3 interfaces are affected by the flag
backend_a.get(backend_a.device, "sfo-spine2").model_flags |= DiffSyncModelFlags.SKIP_UNMATCHED_DST
diff = backend_a.diff_from(backend_a_minus_some_models)
assert diff.summary() == {"create": 0, "update": 0, "delete": 5, "no-change": 11}
assert diff.summary() == {"create": 0, "update": 0, "delete": 5, "no-change": 11, "skip": 2}


def test_diffsync_sync_with_skip_unmatched_dst_flag_on_models(backend_a, backend_a_minus_some_models):
Expand Down