Skip to content

Commit 8502da1

Browse files
committed
Merge branch 'develop' of github.com:opsmill/infrahub into ple-global-activities
2 parents 1e6455b + 927ff90 commit 8502da1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1648
-378
lines changed

.github/workflows/publish-pypi.yml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
# yamllint disable rule:truthy
3-
name: Publish Infrahub-Server Package
4-
3+
name: Publish Infrahub-Server, Infrahub-Testcontainers Packages
54
on:
65
workflow_dispatch:
76
inputs:
@@ -30,39 +29,40 @@ on:
3029

3130
jobs:
3231
publish_to_pypi:
33-
name: "Publish Infrahub SDK to PyPI"
32+
name: "Publish Infrahub-Server and Infrahub-Testcontainers to PyPI"
3433
runs-on: "ubuntu-22.04"
34+
strategy:
35+
matrix:
36+
package_dir: ["", "python_testcontainers"]
3537
steps:
3638
- name: "Set up Python"
3739
uses: "actions/setup-python@v5"
3840
with:
3941
python-version: "3.12"
40-
4142
- name: "Install Poetry"
4243
uses: "snok/install-poetry@v1"
4344
with:
4445
version: 1.8.5
4546
virtualenvs-create: true
4647
virtualenvs-in-project: true
4748
installer-parallel: true
48-
4949
- name: "Check out repository code"
5050
uses: "actions/checkout@v4"
5151
with:
5252
submodules: true
53-
5453
- name: "Install Dependencies"
5554
run: "poetry install"
56-
55+
working-directory: ${{ matrix.package_dir }}
5756
- name: "Add PyPI secret"
5857
run: "poetry config pypi-token.pypi ${{ secrets.PYPI_TOKEN }}"
59-
58+
working-directory: ${{ matrix.package_dir }}
6059
- name: "Poetry build"
6160
run: "poetry build"
62-
61+
working-directory: ${{ matrix.package_dir }}
6362
- name: "show output"
6463
run: "ls -la dist/"
65-
64+
working-directory: ${{ matrix.package_dir }}
6665
- name: "Poetry push PyPI"
6766
if: ${{ inputs.publish }}
6867
run: "poetry publish"
68+
working-directory: ${{ matrix.package_dir }}

.vale/styles/spelling-exceptions.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ graphene
5151
graphiql
5252
graphql
5353
greymatter
54+
healthcheck
5455
hfid
5556
hfids
5657
hostname
@@ -95,6 +96,7 @@ order_weight
9596
openconfig
9697
opentelemetry
9798
order_by
99+
Postgress
98100
Prefetch
99101
profile_name
100102
pseudocode

backend/infrahub/api/schema.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ async def load_schema(
384384
request_id=request_id,
385385
account_id=account_session.account_id,
386386
branch=branch,
387+
context=context,
387388
),
388389
)
389390
await service.event.send(event=event)

backend/infrahub/computed_attribute/tasks.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ async def trigger_update_python_computed_attributes(
170170
"object_id": node.id,
171171
"computed_attribute_name": computed_attribute_name,
172172
"computed_attribute_kind": computed_attribute_kind,
173+
"context": context,
173174
},
174175
)
175176

@@ -315,6 +316,7 @@ async def trigger_update_jinja2_computed_attributes(
315316
"computed_attribute_kind": computed_attribute_kind,
316317
"node_kind": computed_attribute_kind,
317318
"object_id": node.id,
319+
"context": context,
318320
},
319321
)
320322

@@ -383,6 +385,13 @@ async def computed_attribute_setup(
383385
"computed_attribute_name": computed_attribute.attribute.name,
384386
"computed_attribute_kind": computed_attribute.kind,
385387
"updated_fields": "{{ event.payload['fields'] | tojson }}",
388+
"context": {
389+
"__prefect_kind": "json",
390+
"value": {
391+
"__prefect_kind": "jinja",
392+
"template": "{{ event.payload['context'] | tojson }}",
393+
},
394+
},
386395
},
387396
job_variables={},
388397
)
@@ -407,6 +416,7 @@ async def computed_attribute_setup(
407416
"branch_name": registry.default_branch,
408417
"computed_attribute_name": computed_attribute.attribute.name,
409418
"computed_attribute_kind": computed_attribute.kind,
419+
"context": context,
410420
},
411421
)
412422

@@ -448,6 +458,13 @@ async def computed_attribute_setup(
448458
"computed_attribute_name": computed_attribute.attribute.name,
449459
"computed_attribute_kind": computed_attribute.kind,
450460
"updated_fields": "{{ event.payload['fields'] | tojson }}",
461+
"context": {
462+
"__prefect_kind": "json",
463+
"value": {
464+
"__prefect_kind": "jinja",
465+
"template": "{{ event.payload['context'] | tojson }}",
466+
},
467+
},
451468
},
452469
job_variables={},
453470
)
@@ -474,6 +491,7 @@ async def computed_attribute_setup(
474491
"branch_name": branch_name,
475492
"computed_attribute_name": computed_attribute.attribute.name,
476493
"computed_attribute_kind": computed_attribute.kind,
494+
"context": context,
477495
},
478496
)
479497

@@ -565,6 +583,13 @@ async def computed_attribute_setup_python(
565583
"object_id": "{{ event.resource['infrahub.node.id'] }}",
566584
"computed_attribute_name": computed_attribute.computed_attribute.attribute.name,
567585
"computed_attribute_kind": computed_attribute.computed_attribute.kind,
586+
"context": {
587+
"__prefect_kind": "json",
588+
"value": {
589+
"__prefect_kind": "jinja",
590+
"template": "{{ event.payload['context'] | tojson }}",
591+
},
592+
},
568593
},
569594
job_variables={},
570595
)
@@ -613,6 +638,13 @@ async def computed_attribute_setup_python(
613638
"branch_name": "{{ event.resource['infrahub.branch.name'] }}",
614639
"node_kind": "{{ event.resource['infrahub.node.kind'] }}",
615640
"object_id": "{{ event.resource['infrahub.node.id'] }}",
641+
"context": {
642+
"__prefect_kind": "json",
643+
"value": {
644+
"__prefect_kind": "jinja",
645+
"template": "{{ event.payload['context'] | tojson }}",
646+
},
647+
},
616648
},
617649
job_variables={},
618650
)
@@ -641,6 +673,7 @@ async def computed_attribute_setup_python(
641673
"branch_name": branch_name,
642674
"computed_attribute_name": computed_attribute.computed_attribute.attribute.name,
643675
"computed_attribute_kind": computed_attribute.computed_attribute.kind,
676+
"context": context,
644677
},
645678
)
646679

backend/infrahub/computed_attribute/triggers.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
parameters={
1717
"branch_name": "{{ event.resource['infrahub.branch.name'] }}",
1818
"trigger_updates": False,
19+
"context": {
20+
"__prefect_kind": "json",
21+
"value": {"__prefect_kind": "jinja", "template": "{{ event.payload['context'] | tojson }}"},
22+
},
1923
},
2024
)
2125
],
@@ -31,6 +35,10 @@
3135
parameters={
3236
"branch_name": "{{ event.resource['infrahub.branch.name'] }}",
3337
"commit": "{{ event.payload['commit'] }}",
38+
"context": {
39+
"__prefect_kind": "json",
40+
"value": {"__prefect_kind": "jinja", "template": "{{ event.payload['context'] | tojson }}"},
41+
},
3442
},
3543
)
3644
],
@@ -45,6 +53,10 @@
4553
name=COMPUTED_ATTRIBUTE_REMOVE_PYTHON.name,
4654
parameters={
4755
"branch_name": "{{ event.resource['infrahub.branch.name'] }}",
56+
"context": {
57+
"__prefect_kind": "json",
58+
"value": {"__prefect_kind": "jinja", "template": "{{ event.payload['context'] | tojson }}"},
59+
},
4860
},
4961
)
5062
],
@@ -58,12 +70,20 @@
5870
name=COMPUTED_ATTRIBUTE_SETUP.name,
5971
parameters={
6072
"branch_name": "{{ event.resource['infrahub.branch.name'] }}",
73+
"context": {
74+
"__prefect_kind": "json",
75+
"value": {"__prefect_kind": "jinja", "template": "{{ event.payload['context'] | tojson }}"},
76+
},
6177
},
6278
),
6379
ExecuteWorkflow(
6480
name=COMPUTED_ATTRIBUTE_SETUP_PYTHON.name,
6581
parameters={
6682
"branch_name": "{{ event.resource['infrahub.branch.name'] }}",
83+
"context": {
84+
"__prefect_kind": "json",
85+
"value": {"__prefect_kind": "jinja", "template": "{{ event.payload['context'] | tojson }}"},
86+
},
6787
},
6888
),
6989
],

backend/infrahub/core/branch/tasks.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,9 @@ async def rebase_branch(branch: str, context: InfrahubContext, service: Infrahub
155155
# -------------------------------------------------------------
156156
# TODO Add account information
157157
await service.event.send(
158-
event=BranchRebasedEvent(branch_name=obj.name, branch_id=str(obj.uuid), meta=EventMeta(branch=obj))
158+
event=BranchRebasedEvent(
159+
branch_name=obj.name, branch_id=str(obj.uuid), meta=EventMeta(branch=obj, context=context)
160+
)
159161
)
160162

161163

@@ -250,7 +252,10 @@ async def delete_branch(branch: str, context: InfrahubContext, service: Infrahub
250252
await obj.delete(db=db)
251253

252254
event = BranchDeletedEvent(
253-
branch_name=branch, branch_id=str(obj.uuid), sync_with_git=obj.sync_with_git, meta=EventMeta(branch=obj)
255+
branch_name=branch,
256+
branch_id=str(obj.uuid),
257+
sync_with_git=obj.sync_with_git,
258+
meta=EventMeta(branch=obj, context=context),
254259
)
255260

256261
await service.workflow.submit_workflow(
@@ -318,7 +323,9 @@ async def create_branch(model: BranchCreateModel, context: InfrahubContext, serv
318323
branch_name=obj.name,
319324
branch_id=str(obj.uuid),
320325
sync_with_git=obj.sync_with_git,
321-
meta=EventMeta(branch=obj, account_id=context.account.account_id, initiator_id=WORKER_IDENTITY),
326+
meta=EventMeta(
327+
branch=obj, account_id=context.account.account_id, initiator_id=WORKER_IDENTITY, context=context
328+
),
322329
)
323330
await service.event.send(event=event)
324331

backend/infrahub/core/changelog/models.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99

1010
if TYPE_CHECKING:
1111
from infrahub.core.attribute import BaseAttribute
12+
from infrahub.core.branch import Branch
1213
from infrahub.core.manager import RelationshipSchema
1314
from infrahub.core.query.relationship import RelationshipPeerData
1415
from infrahub.core.relationship.model import Relationship
16+
from infrahub.database import InfrahubDatabase
1517

1618

1719
class PropertyChangelog(BaseModel):
@@ -221,6 +223,11 @@ class NodeChangelog(BaseModel):
221223
def parent(self) -> ChangelogNodeParent | None:
222224
return self._parent
223225

226+
@property
227+
def updated_fields(self) -> list[str]:
228+
"""Return a list of update fields i.e. attributes and relationships"""
229+
return list(self.relationships.keys()) + list(self.attributes.keys())
230+
224231
@property
225232
def root_node_id(self) -> str:
226233
"""Return the top level node_id"""
@@ -404,3 +411,50 @@ def changelog(self) -> RelationshipCardinalityOneChangelog | RelationshipCardina
404411
return self.cardinality_one_relationship
405412
case RelationshipCardinality.MANY:
406413
return self.cardinality_many_relationship
414+
415+
416+
class RelationshipChangelogGetter:
417+
def __init__(self, db: InfrahubDatabase, branch: Branch) -> None:
418+
self._db = db
419+
self._branch = branch
420+
421+
async def get_changelogs(self, primary_changelog: NodeChangelog) -> list[NodeChangelog]:
422+
"""Return secondary changelogs based on this update
423+
424+
These will typically include updates to relationships on other nodes.
425+
"""
426+
schema_branch = self._db.schema.get_schema_branch(name=self._branch.name)
427+
node_schema = schema_branch.get(name=primary_changelog.node_kind)
428+
secondaries: list[NodeChangelog] = []
429+
430+
for relationship in primary_changelog.relationships.values():
431+
rel_schema = node_schema.get_relationship(name=relationship.name)
432+
if isinstance(relationship, RelationshipCardinalityOneChangelog):
433+
# For now this code only looks at the scenario when a cardinality=one relationship
434+
# is added to a node and it has a cardinality=many relationship coming back from
435+
# another node, it will be expanded to include all variations.
436+
if relationship.peer_status == DiffAction.ADDED:
437+
peer_schema = schema_branch.get(name=str(relationship.peer_kind))
438+
peer_relation = peer_schema.get_relationship_by_identifier(
439+
id=str(rel_schema.identifier), raise_on_error=False
440+
)
441+
if peer_relation:
442+
node_changelog = NodeChangelog(
443+
node_id=str(relationship.peer_id),
444+
node_kind=str(relationship.peer_kind),
445+
display_label="n/a",
446+
)
447+
if peer_relation.cardinality == RelationshipCardinality.MANY:
448+
node_changelog.relationships[peer_relation.name] = RelationshipCardinalityManyChangelog(
449+
name=peer_relation.name,
450+
peers=[
451+
RelationshipPeerChangelog(
452+
peer_id=primary_changelog.node_id,
453+
peer_kind=primary_changelog.node_kind,
454+
peer_status=DiffAction.ADDED,
455+
)
456+
],
457+
)
458+
secondaries.append(node_changelog)
459+
460+
return secondaries

backend/infrahub/core/constants/__init__.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -289,18 +289,6 @@ class AttributeDBNodeType(InfrahubStringEnum):
289289
IPNETWORK = "ipnetwork"
290290

291291

292-
class EventLevel(InfrahubStringEnum):
293-
ZERO = "zero"
294-
ONE = "one"
295-
296-
def to_int(self) -> int:
297-
match self:
298-
case EventLevel.ZERO:
299-
return 0
300-
case EventLevel.ONE:
301-
return 1
302-
303-
304292
RESTRICTED_NAMESPACES: list[str] = [
305293
"Account",
306294
"Branch",

backend/infrahub/core/diff/combiner.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,8 @@ def _combine_relationships(
342342

343343
def _copy_node_without_parents(self, node: EnrichedDiffNode) -> EnrichedDiffNode:
344344
rels_without_parents = {replace(r, nodes=set()) for r in node.relationships}
345+
for rel in rels_without_parents:
346+
rel.reset_summaries()
345347
node_without_parents = replace(node, relationships=rels_without_parents)
346348
return deepcopy(node_without_parents)
347349

@@ -351,15 +353,11 @@ def _combine_nodes(self, node_pairs: list[NodePair]) -> set[EnrichedDiffNode]:
351353
if node_pair.earlier is None:
352354
if node_pair.later is not None:
353355
copied = self._copy_node_without_parents(node_pair.later)
354-
for rel in copied.relationships:
355-
rel.reset_summaries()
356356
combined_nodes.add(copied)
357357
continue
358358
if node_pair.later is None:
359359
if node_pair.earlier is not None:
360360
copied = self._copy_node_without_parents(node_pair.earlier)
361-
for rel in copied.relationships:
362-
rel.reset_summaries()
363361
combined_nodes.add(copied)
364362
continue
365363
combined_attributes = self._combine_attributes(

0 commit comments

Comments
 (0)