MAC Address values format update#9149
Conversation
…8 form (closes #9015) Adds an input-time `_normalize_value()` hook on `BaseAttribute` (no-op default), overridden in `MacAddress` to emit colon-uppercase form (`AA:BB:CC:DD:EE:FF`). Adds m070 migration that rewrites stored MAC values + dependent HFIDs / display labels in the DB. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
| form (`AA:BB:CC:DD:EE:FF`) per issue #9015. | ||
|
|
||
| Pre-existing values may be in any form accepted by ``netaddr.EUI`` — on | ||
| `stable`, ``serialize_value`` produces dash-uppercase form, but |
There was a problem hiding this comment.
stable or other branches in the repo shouldn't be referenced in here. unless I am misunderstanding what "stable" means in this context
There was a problem hiding this comment.
I have missed it, thanks I think the bot added this one because I mentioned some dependencies with other PR and default stable branch behavior. My bad
| if node_schema_name in SCHEMA_KINDS_TO_SKIP: | ||
| continue | ||
| schema = schema_branch.get_node(name=node_schema_name, duplicate=False) | ||
| if schema.branch not in branch_filter: |
There was a problem hiding this comment.
it's possible for an attribute to be branch-aware on a branch-agnostic/local schema. so perhaps this filter should move down a layer
| AND e1.status = "active" | ||
| AND e2.branch IN $branch_names | ||
| AND e2.to IS NULL | ||
| AND e2.status = "active" |
There was a problem hiding this comment.
can you add AND n.uuid <> peer.uuid here to prevent paths that loop back to the same Node?
There was a problem hiding this comment.
Added there and in two other locations 76ed870
| set_display_label: str | None = None, | ||
| ) -> Node: | ||
| """Create a node, then rewrite MAC + (optional) HFID + display_label so the DB matches the | ||
| legacy on-stable storage form: MacAddress stored as EUI-48 dash form.""" |
| default_branch.update_schema_hash() | ||
| gql_params = await prepare_graphql_params(db=db, branch=default_branch) | ||
| pre_result = await graphql( | ||
| schema=gql_params.schema, | ||
| source=INTERFACE_BY_ID_QUERY, | ||
| context_value=gql_params.context, | ||
| root_value=None, | ||
| variable_values={"ids": [node.id]}, | ||
| ) | ||
| assert pre_result.errors is None, pre_result.errors | ||
| assert pre_result.data is not None | ||
| pre_edge = pre_result.data["TestingInterface"]["edges"][0]["node"] | ||
| assert pre_edge["hfid"] == [LEGACY_DASH_MAC] | ||
| assert pre_edge["display_label"] == legacy_display_label |
There was a problem hiding this comment.
we usually don't do graphql layer testing in migration tests. verifying the database should be enough
| return node | ||
|
|
||
|
|
||
| class TestMigration070(TestInfrahubApp): |
There was a problem hiding this comment.
can you add a call to verify_graph from db_validation.py to the end of each of these test cases to ensure nothing is getting duplicated or orphaned please?
| await node.new(db=db, name=node_name, mac=LEGACY_DASH_MAC) | ||
| await node.save(db=db) | ||
|
|
||
| # Mimic legacy on-stable state on the branch: dash-form MAC stored on disk plus dash-form HFID + display_label. |
There was a problem hiding this comment.
I think it's worth considering consolidating these test cases into a single test case that I think would save some time. something like this
- load data for default and user branches, including single object with different values on both
- run migration on default
- rebase user branch
- run migration on user branch
- verify data
- run the migrations again to check idempotency
- verify data again
- verify_graph()
There was a problem hiding this comment.
Ok let's do this, I will do the same in the PR containing the migration 71
| @@ -0,0 +1,406 @@ | |||
| from __future__ import annotations | |||
There was a problem hiding this comment.
With the inversion of both PRs, this code is currently duplicated, but will be removed from original class in the next PR
- file
backend/infrahub/core/migrations/graph/m044_backfill_hfid_display_label_in_db.py - Pr https://github.com/opsmill/infrahub/pull/8904/changes
| - `Dropdown`: A list of choices, each choice can have a color and description | ||
| - `Email`: Email address | ||
| - `Password`: A Text String that should be obfuscated but which can be read with enough right in the UI | ||
| - `HashedPassword`: Similar to Password but it will not be shown in the UI and can't be re-read. |
There was a problem hiding this comment.
I'll just push the removal of this documentation change regarding product work on documentation
| branch=default_branch, | ||
| at=migration_input.at, | ||
| branch_filter=(BranchSupportType.AWARE,), | ||
| ) |
There was a problem hiding this comment.
should have thought of this before, but I think that the branch-filtering will exclude any branch-agnostic MAC address attributes
There was a problem hiding this comment.
AGNOSTIC tackled on default_branch process, AWARE & LOCAL on both
There was a problem hiding this comment.
Also applied on M071
| db=migration_input.db, | ||
| branch=default_branch, | ||
| at=migration_input.at, | ||
| branch_filter=(BranchSupportType.AWARE,), |
There was a problem hiding this comment.
this looks like it skips branch-local MAC attributes on the default branch
Why
MAC address values are standardized to the following form: 01-23-45-67-89-AB.
Expected standardized form is 01:23:45:67:89:AB.
Closes #9015 and IFC-2494
What
This PR updates the standardization method against MAC address values, and adds a migration to update any existing MAC address attributes or existing display labels/HFID that would reference such attribute. It also introduces the
_normalize_value()framework hook onBaseAttribute(no-op by default), overridden inMacAddressto canonicalize input directly to colon-uppercase EUI-48 form.Stack ordering
PR #8904 (IPHost/IPNetwork normalization + HFID/display-label recompute migration) is now stacked on top of this PR. m070 (this PR) normalizes MAC values; m071 (PR #8904) recomputes IP HFIDs/display labels and benefits from MAC values being already in colon form.
Note on history
This branch was originally PR #9134, but GitHub auto-marked that PR as "merged" when the previous force-push made the head reachable from its old base branch. This PR recreates it; it carries the same head branch (
pmi-20260504-mac-address-values) with one rebuilt commit on top ofstable.