infrahub-server 1.3.8__py3-none-any.whl → 1.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- infrahub/api/internal.py +5 -0
- infrahub/artifacts/tasks.py +17 -22
- infrahub/branch/merge_mutation_checker.py +38 -0
- infrahub/cli/__init__.py +2 -2
- infrahub/cli/context.py +7 -3
- infrahub/cli/db.py +5 -16
- infrahub/cli/upgrade.py +10 -29
- infrahub/computed_attribute/tasks.py +36 -46
- infrahub/config.py +57 -6
- infrahub/constants/environment.py +1 -0
- infrahub/core/attribute.py +15 -7
- infrahub/core/branch/tasks.py +43 -41
- infrahub/core/constants/__init__.py +21 -6
- infrahub/core/constants/infrahubkind.py +2 -0
- infrahub/core/diff/coordinator.py +3 -1
- infrahub/core/diff/repository/repository.py +0 -8
- infrahub/core/diff/tasks.py +11 -8
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/graph/index.py +1 -2
- infrahub/core/graph/schema.py +50 -29
- infrahub/core/initialization.py +81 -47
- infrahub/core/ipam/tasks.py +4 -3
- infrahub/core/merge.py +8 -10
- infrahub/core/migrations/__init__.py +2 -0
- infrahub/core/migrations/graph/__init__.py +4 -0
- infrahub/core/migrations/graph/m036_drop_attr_value_index.py +45 -0
- infrahub/core/migrations/graph/m037_index_attr_vals.py +577 -0
- infrahub/core/migrations/query/attribute_add.py +27 -2
- infrahub/core/migrations/schema/attribute_kind_update.py +156 -0
- infrahub/core/migrations/schema/tasks.py +6 -5
- infrahub/core/models.py +5 -1
- infrahub/core/node/proposed_change.py +43 -0
- infrahub/core/protocols.py +12 -0
- infrahub/core/query/attribute.py +32 -14
- infrahub/core/query/diff.py +11 -0
- infrahub/core/query/ipam.py +13 -7
- infrahub/core/query/node.py +51 -10
- infrahub/core/query/resource_manager.py +3 -3
- infrahub/core/schema/basenode_schema.py +8 -0
- infrahub/core/schema/definitions/core/__init__.py +10 -1
- infrahub/core/schema/definitions/core/ipam.py +28 -2
- infrahub/core/schema/definitions/core/propose_change.py +15 -0
- infrahub/core/schema/definitions/core/webhook.py +3 -0
- infrahub/core/schema/definitions/internal.py +1 -1
- infrahub/core/schema/generated/attribute_schema.py +1 -1
- infrahub/core/schema/generic_schema.py +10 -0
- infrahub/core/schema/manager.py +10 -1
- infrahub/core/schema/node_schema.py +22 -17
- infrahub/core/schema/profile_schema.py +8 -0
- infrahub/core/schema/schema_branch.py +9 -5
- infrahub/core/schema/template_schema.py +8 -0
- infrahub/core/validators/attribute/kind.py +5 -1
- infrahub/core/validators/checks_runner.py +5 -5
- infrahub/core/validators/determiner.py +22 -2
- infrahub/core/validators/tasks.py +6 -7
- infrahub/core/validators/uniqueness/checker.py +4 -2
- infrahub/core/validators/uniqueness/model.py +1 -0
- infrahub/core/validators/uniqueness/query.py +57 -7
- infrahub/database/__init__.py +2 -1
- infrahub/events/__init__.py +20 -0
- infrahub/events/constants.py +7 -0
- infrahub/events/generator.py +29 -2
- infrahub/events/proposed_change_action.py +203 -0
- infrahub/generators/tasks.py +24 -20
- infrahub/git/base.py +4 -7
- infrahub/git/integrator.py +21 -12
- infrahub/git/repository.py +15 -30
- infrahub/git/tasks.py +121 -106
- infrahub/graphql/field_extractor.py +69 -0
- infrahub/graphql/manager.py +15 -11
- infrahub/graphql/mutations/account.py +2 -2
- infrahub/graphql/mutations/action.py +8 -2
- infrahub/graphql/mutations/artifact_definition.py +4 -1
- infrahub/graphql/mutations/branch.py +10 -5
- infrahub/graphql/mutations/graphql_query.py +2 -1
- infrahub/graphql/mutations/main.py +14 -8
- infrahub/graphql/mutations/menu.py +2 -1
- infrahub/graphql/mutations/proposed_change.py +230 -8
- infrahub/graphql/mutations/relationship.py +5 -0
- infrahub/graphql/mutations/repository.py +2 -1
- infrahub/graphql/mutations/tasks.py +7 -9
- infrahub/graphql/mutations/webhook.py +4 -1
- infrahub/graphql/parser.py +15 -6
- infrahub/graphql/queries/__init__.py +10 -1
- infrahub/graphql/queries/account.py +3 -3
- infrahub/graphql/queries/branch.py +2 -2
- infrahub/graphql/queries/diff/tree.py +3 -3
- infrahub/graphql/queries/event.py +13 -3
- infrahub/graphql/queries/ipam.py +23 -1
- infrahub/graphql/queries/proposed_change.py +84 -0
- infrahub/graphql/queries/relationship.py +2 -2
- infrahub/graphql/queries/resource_manager.py +3 -3
- infrahub/graphql/queries/search.py +3 -2
- infrahub/graphql/queries/status.py +3 -2
- infrahub/graphql/queries/task.py +2 -2
- infrahub/graphql/resolvers/ipam.py +440 -0
- infrahub/graphql/resolvers/many_relationship.py +4 -3
- infrahub/graphql/resolvers/resolver.py +5 -5
- infrahub/graphql/resolvers/single_relationship.py +3 -2
- infrahub/graphql/schema.py +25 -5
- infrahub/graphql/types/__init__.py +2 -2
- infrahub/graphql/types/attribute.py +3 -3
- infrahub/graphql/types/event.py +68 -0
- infrahub/groups/tasks.py +6 -6
- infrahub/lock.py +3 -2
- infrahub/menu/generator.py +8 -0
- infrahub/message_bus/operations/__init__.py +9 -12
- infrahub/message_bus/operations/git/file.py +6 -5
- infrahub/message_bus/operations/git/repository.py +12 -20
- infrahub/message_bus/operations/refresh/registry.py +15 -9
- infrahub/message_bus/operations/send/echo.py +7 -4
- infrahub/message_bus/types.py +1 -0
- infrahub/permissions/__init__.py +2 -1
- infrahub/permissions/constants.py +13 -0
- infrahub/permissions/globals.py +31 -2
- infrahub/permissions/manager.py +8 -5
- infrahub/pools/prefix.py +7 -5
- infrahub/prefect_server/app.py +31 -0
- infrahub/prefect_server/bootstrap.py +18 -0
- infrahub/proposed_change/action_checker.py +206 -0
- infrahub/proposed_change/approval_revoker.py +40 -0
- infrahub/proposed_change/branch_diff.py +3 -1
- infrahub/proposed_change/checker.py +45 -0
- infrahub/proposed_change/constants.py +32 -2
- infrahub/proposed_change/tasks.py +182 -150
- infrahub/py.typed +0 -0
- infrahub/server.py +29 -17
- infrahub/services/__init__.py +13 -28
- infrahub/services/adapters/cache/__init__.py +4 -0
- infrahub/services/adapters/cache/nats.py +2 -0
- infrahub/services/adapters/cache/redis.py +3 -0
- infrahub/services/adapters/message_bus/__init__.py +0 -2
- infrahub/services/adapters/message_bus/local.py +1 -2
- infrahub/services/adapters/message_bus/nats.py +6 -8
- infrahub/services/adapters/message_bus/rabbitmq.py +7 -9
- infrahub/services/adapters/workflow/__init__.py +1 -0
- infrahub/services/adapters/workflow/local.py +1 -8
- infrahub/services/component.py +2 -1
- infrahub/task_manager/event.py +56 -0
- infrahub/task_manager/models.py +9 -0
- infrahub/tasks/artifact.py +6 -7
- infrahub/tasks/check.py +4 -7
- infrahub/telemetry/tasks.py +15 -18
- infrahub/transformations/tasks.py +10 -6
- infrahub/trigger/tasks.py +4 -3
- infrahub/types.py +4 -0
- infrahub/validators/events.py +7 -7
- infrahub/validators/tasks.py +6 -7
- infrahub/webhook/models.py +45 -45
- infrahub/webhook/tasks.py +25 -24
- infrahub/workers/dependencies.py +143 -0
- infrahub/workers/infrahub_async.py +19 -43
- infrahub/workflows/catalogue.py +16 -2
- infrahub/workflows/initialization.py +5 -4
- infrahub/workflows/models.py +2 -0
- infrahub_sdk/client.py +2 -2
- infrahub_sdk/ctl/repository.py +51 -0
- infrahub_sdk/ctl/schema.py +9 -9
- infrahub_sdk/node/node.py +2 -2
- infrahub_sdk/pytest_plugin/items/graphql_query.py +1 -1
- infrahub_sdk/schema/repository.py +1 -1
- infrahub_sdk/testing/docker.py +1 -1
- infrahub_sdk/utils.py +2 -2
- {infrahub_server-1.3.8.dist-info → infrahub_server-1.4.0.dist-info}/METADATA +7 -5
- {infrahub_server-1.3.8.dist-info → infrahub_server-1.4.0.dist-info}/RECORD +172 -156
- infrahub_testcontainers/container.py +17 -0
- infrahub_testcontainers/docker-compose-cluster.test.yml +56 -1
- infrahub_testcontainers/docker-compose.test.yml +56 -1
- infrahub_testcontainers/helpers.py +4 -1
- {infrahub_server-1.3.8.dist-info → infrahub_server-1.4.0.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.3.8.dist-info → infrahub_server-1.4.0.dist-info}/WHEEL +0 -0
- {infrahub_server-1.3.8.dist-info → infrahub_server-1.4.0.dist-info}/entry_points.txt +0 -0
|
@@ -3,12 +3,12 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import TYPE_CHECKING, Any
|
|
4
4
|
|
|
5
5
|
from graphql.type.definition import GraphQLNonNull
|
|
6
|
-
from infrahub_sdk.utils import extract_fields
|
|
7
6
|
from opentelemetry import trace
|
|
8
7
|
|
|
9
8
|
from infrahub.core.constants import BranchSupportType, InfrahubKind, RelationshipHierarchyDirection
|
|
10
9
|
from infrahub.core.manager import NodeManager
|
|
11
10
|
from infrahub.exceptions import NodeNotFoundError
|
|
11
|
+
from infrahub.graphql.field_extractor import extract_graphql_fields
|
|
12
12
|
|
|
13
13
|
from ..models import OrderModel
|
|
14
14
|
from ..parser import extract_selection
|
|
@@ -26,7 +26,7 @@ async def account_resolver(
|
|
|
26
26
|
root: dict, # noqa: ARG001
|
|
27
27
|
info: GraphQLResolveInfo,
|
|
28
28
|
) -> dict:
|
|
29
|
-
fields =
|
|
29
|
+
fields = extract_graphql_fields(info=info)
|
|
30
30
|
graphql_context: GraphqlContext = info.context
|
|
31
31
|
|
|
32
32
|
async with graphql_context.db.start_session(read_only=True) as db:
|
|
@@ -90,7 +90,7 @@ async def default_resolver(*args: Any, **kwargs) -> dict | list[dict] | None:
|
|
|
90
90
|
graphql_context: GraphqlContext = info.context
|
|
91
91
|
|
|
92
92
|
# Extract the name of the fields in the GQL query
|
|
93
|
-
fields =
|
|
93
|
+
fields = extract_graphql_fields(info=info)
|
|
94
94
|
|
|
95
95
|
# Extract the schema of the node on the other end of the relationship from the GQL Schema
|
|
96
96
|
node_rel = node_schema.get_relationship(info.field_name)
|
|
@@ -155,7 +155,7 @@ async def default_paginated_list_resolver(
|
|
|
155
155
|
else info.return_type.graphene_type._meta.schema
|
|
156
156
|
)
|
|
157
157
|
|
|
158
|
-
fields = await extract_selection(info
|
|
158
|
+
fields = await extract_selection(info=info, schema=schema)
|
|
159
159
|
|
|
160
160
|
graphql_context: GraphqlContext = info.context
|
|
161
161
|
async with graphql_context.db.start_session(read_only=True) as db:
|
|
@@ -277,7 +277,7 @@ async def hierarchy_resolver(
|
|
|
277
277
|
graphql_context: GraphqlContext = info.context
|
|
278
278
|
|
|
279
279
|
# Extract the name of the fields in the GQL query
|
|
280
|
-
fields =
|
|
280
|
+
fields = extract_graphql_fields(info=info)
|
|
281
281
|
edges = fields.get("edges", {})
|
|
282
282
|
node_fields = edges.get("node", {})
|
|
283
283
|
|
|
@@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Any
|
|
|
2
2
|
|
|
3
3
|
from graphql import GraphQLResolveInfo
|
|
4
4
|
from graphql.type.definition import GraphQLNonNull
|
|
5
|
-
from infrahub_sdk.utils import deep_merge_dict
|
|
5
|
+
from infrahub_sdk.utils import deep_merge_dict
|
|
6
6
|
|
|
7
7
|
from infrahub.core.branch.models import Branch
|
|
8
8
|
from infrahub.core.constants import BranchSupportType
|
|
@@ -10,6 +10,7 @@ from infrahub.core.manager import NodeManager
|
|
|
10
10
|
from infrahub.core.schema.relationship_schema import RelationshipSchema
|
|
11
11
|
from infrahub.core.timestamp import Timestamp
|
|
12
12
|
from infrahub.database import InfrahubDatabase
|
|
13
|
+
from infrahub.graphql.field_extractor import extract_graphql_fields
|
|
13
14
|
|
|
14
15
|
from ..loaders.node import GetManyParams, NodeDataLoader
|
|
15
16
|
from ..types import RELATIONS_PROPERTY_MAP, RELATIONS_PROPERTY_MAP_REVERSED
|
|
@@ -42,7 +43,7 @@ class SingleRelationshipResolver:
|
|
|
42
43
|
graphql_context: GraphqlContext = info.context
|
|
43
44
|
|
|
44
45
|
# Extract the name of the fields in the GQL query
|
|
45
|
-
fields =
|
|
46
|
+
fields = extract_graphql_fields(info=info)
|
|
46
47
|
node_fields = fields.get("node", {})
|
|
47
48
|
property_fields = fields.get("properties", {})
|
|
48
49
|
for key, value in property_fields.items():
|
infrahub/graphql/schema.py
CHANGED
|
@@ -20,7 +20,12 @@ from .mutations.convert_object_type import ConvertObjectType
|
|
|
20
20
|
from .mutations.diff import DiffUpdateMutation
|
|
21
21
|
from .mutations.diff_conflict import ResolveDiffConflict
|
|
22
22
|
from .mutations.generator import GeneratorDefinitionRequestRun
|
|
23
|
-
from .mutations.proposed_change import
|
|
23
|
+
from .mutations.proposed_change import (
|
|
24
|
+
ProposedChangeCheckForApprovalRevoke,
|
|
25
|
+
ProposedChangeMerge,
|
|
26
|
+
ProposedChangeRequestRunCheck,
|
|
27
|
+
ProposedChangeReview,
|
|
28
|
+
)
|
|
24
29
|
from .mutations.relationship import RelationshipAdd, RelationshipRemove
|
|
25
30
|
from .mutations.repository import ProcessRepository, ValidateRepositoryConnectivity
|
|
26
31
|
from .mutations.resource_manager import IPAddressPoolGetResource, IPPrefixPoolGetResource
|
|
@@ -29,6 +34,8 @@ from .queries import (
|
|
|
29
34
|
AccountPermissions,
|
|
30
35
|
AccountToken,
|
|
31
36
|
BranchQueryList,
|
|
37
|
+
DeprecatedIPAddressGetNextAvailable,
|
|
38
|
+
DeprecatedIPPrefixGetNextAvailable,
|
|
32
39
|
InfrahubInfo,
|
|
33
40
|
InfrahubIPAddressGetNextAvailable,
|
|
34
41
|
InfrahubIPPrefixGetNextAvailable,
|
|
@@ -36,6 +43,7 @@ from .queries import (
|
|
|
36
43
|
InfrahubResourcePoolUtilization,
|
|
37
44
|
InfrahubSearchAnywhere,
|
|
38
45
|
InfrahubStatus,
|
|
46
|
+
ProposedChangeAvailableActions,
|
|
39
47
|
Relationship,
|
|
40
48
|
)
|
|
41
49
|
from .queries.convert_object_type_mapping import FieldsMappingTypeConversion
|
|
@@ -63,8 +71,12 @@ class InfrahubBaseQuery(ObjectType):
|
|
|
63
71
|
InfrahubEvent = Event
|
|
64
72
|
InfrahubTaskBranchStatus = TaskBranchStatus
|
|
65
73
|
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
CoreProposedChangeAvailableActions = ProposedChangeAvailableActions
|
|
75
|
+
|
|
76
|
+
IPAddressGetNextAvailable = DeprecatedIPAddressGetNextAvailable
|
|
77
|
+
IPPrefixGetNextAvailable = DeprecatedIPPrefixGetNextAvailable
|
|
78
|
+
InfrahubIPAddressGetNextAvailable = InfrahubIPAddressGetNextAvailable
|
|
79
|
+
InfrahubIPPrefixGetNextAvailable = InfrahubIPPrefixGetNextAvailable
|
|
68
80
|
InfrahubResourcePoolAllocated = InfrahubResourcePoolAllocated
|
|
69
81
|
InfrahubResourcePoolUtilization = InfrahubResourcePoolUtilization
|
|
70
82
|
|
|
@@ -77,10 +89,17 @@ class InfrahubBaseMutation(ObjectType):
|
|
|
77
89
|
InfrahubAccountTokenDelete = InfrahubAccountTokenDelete.Field()
|
|
78
90
|
CoreProposedChangeRunCheck = ProposedChangeRequestRunCheck.Field()
|
|
79
91
|
CoreProposedChangeMerge = ProposedChangeMerge.Field()
|
|
92
|
+
CoreProposedChangeReview = ProposedChangeReview.Field()
|
|
80
93
|
CoreGeneratorDefinitionRun = GeneratorDefinitionRequestRun.Field()
|
|
81
94
|
|
|
82
|
-
|
|
83
|
-
|
|
95
|
+
InfrahubIPPrefixPoolGetResource = IPPrefixPoolGetResource.Field()
|
|
96
|
+
InfrahubIPAddressPoolGetResource = IPAddressPoolGetResource.Field()
|
|
97
|
+
IPPrefixPoolGetResource = IPPrefixPoolGetResource.Field(
|
|
98
|
+
deprecation_reason="This mutation has been renamed to 'InfrahubIPPrefixPoolGetResource'. It will be removed in the next version of Infrahub."
|
|
99
|
+
)
|
|
100
|
+
IPAddressPoolGetResource = IPAddressPoolGetResource.Field(
|
|
101
|
+
deprecation_reason="This mutation has been renamed to 'InfrahubIPAddressPoolGetResource'. It will be removed in the next version of Infrahub."
|
|
102
|
+
)
|
|
84
103
|
|
|
85
104
|
BranchCreate = BranchCreate.Field()
|
|
86
105
|
BranchDelete = BranchDelete.Field()
|
|
@@ -104,3 +123,4 @@ class InfrahubBaseMutation(ObjectType):
|
|
|
104
123
|
ResolveDiffConflict = ResolveDiffConflict.Field()
|
|
105
124
|
|
|
106
125
|
ConvertObjectType = ConvertObjectType.Field()
|
|
126
|
+
CoreProposedChangeCheckForApprovalRevoke = ProposedChangeCheckForApprovalRevoke.Field()
|
|
@@ -16,8 +16,8 @@ from .attribute import (
|
|
|
16
16
|
MacAddressType,
|
|
17
17
|
NumberAttributeType,
|
|
18
18
|
RelatedIPAddressNodeInput,
|
|
19
|
+
RelatedIPPrefixNodeInput,
|
|
19
20
|
RelatedNodeInput,
|
|
20
|
-
RelatedPrefixNodeInput,
|
|
21
21
|
StrAttributeType,
|
|
22
22
|
TextAttributeType,
|
|
23
23
|
)
|
|
@@ -51,8 +51,8 @@ __all__ = [
|
|
|
51
51
|
"NumberAttributeType",
|
|
52
52
|
"PaginatedObjectPermission",
|
|
53
53
|
"RelatedIPAddressNodeInput",
|
|
54
|
+
"RelatedIPPrefixNodeInput",
|
|
54
55
|
"RelatedNodeInput",
|
|
55
|
-
"RelatedPrefixNodeInput",
|
|
56
56
|
"RelationshipNode",
|
|
57
57
|
"StrAttributeType",
|
|
58
58
|
"TaskLog",
|
|
@@ -32,7 +32,7 @@ class IPAddressPoolInput(GenericPoolInput):
|
|
|
32
32
|
prefixlen = Int(required=False)
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
class
|
|
35
|
+
class IPPrefixPoolInput(GenericPoolInput):
|
|
36
36
|
size = Int(required=False)
|
|
37
37
|
member_type = String(required=False)
|
|
38
38
|
prefix_type = String(required=False)
|
|
@@ -47,10 +47,10 @@ class RelatedIPAddressNodeInput(InputObjectType):
|
|
|
47
47
|
_relation__source = String(required=False)
|
|
48
48
|
|
|
49
49
|
|
|
50
|
-
class
|
|
50
|
+
class RelatedIPPrefixNodeInput(InputObjectType):
|
|
51
51
|
id = String(required=False)
|
|
52
52
|
hfid = Field(List(of_type=String), required=False)
|
|
53
|
-
from_pool = Field(
|
|
53
|
+
from_pool = Field(IPPrefixPoolInput, required=False)
|
|
54
54
|
_relation__is_visible = Boolean(required=False)
|
|
55
55
|
_relation__is_protected = Boolean(required=False)
|
|
56
56
|
_relation__owner = String(required=False)
|
infrahub/graphql/types/event.py
CHANGED
|
@@ -113,6 +113,65 @@ class BranchDeletedEvent(ObjectType):
|
|
|
113
113
|
payload = Field(GenericScalar, required=True)
|
|
114
114
|
|
|
115
115
|
|
|
116
|
+
# ---------------------------------------
|
|
117
|
+
# Proposed change events
|
|
118
|
+
# ---------------------------------------
|
|
119
|
+
class ProposedChangeReviewEvent(ObjectType):
|
|
120
|
+
class Meta:
|
|
121
|
+
interfaces = (EventNodeInterface,)
|
|
122
|
+
|
|
123
|
+
reviewer_account_id = String(required=True, description="The ID of the user who reviewed the proposed change")
|
|
124
|
+
reviewer_account_name = String(required=True, description="The name of the user who reviewed the proposed change")
|
|
125
|
+
reviewer_decision = String(required=True, description="The decision made by the reviewer")
|
|
126
|
+
payload = Field(GenericScalar, required=True)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class ProposedChangeReviewRevokedEvent(ObjectType):
|
|
130
|
+
class Meta:
|
|
131
|
+
interfaces = (EventNodeInterface,)
|
|
132
|
+
|
|
133
|
+
reviewer_account_id = String(required=True, description="The ID of the user who reviewed the proposed change")
|
|
134
|
+
reviewer_account_name = String(required=True, description="The name of the user who reviewed the proposed change")
|
|
135
|
+
reviewer_former_decision = String(required=True, description="The decision made by the reviewer")
|
|
136
|
+
payload = Field(GenericScalar, required=True)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class ProposedChangeApprovalsRevokedEvent(ObjectType):
|
|
140
|
+
class Meta:
|
|
141
|
+
interfaces = (EventNodeInterface,)
|
|
142
|
+
|
|
143
|
+
payload = Field(GenericScalar, required=True)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class ProposedChangeReviewRequestedEvent(ObjectType):
|
|
147
|
+
class Meta:
|
|
148
|
+
interfaces = (EventNodeInterface,)
|
|
149
|
+
|
|
150
|
+
requested_by_account_id = String(
|
|
151
|
+
required=True, description="The ID of the user who requested the proposed change to be reviewed"
|
|
152
|
+
)
|
|
153
|
+
requested_by_account_name = String(
|
|
154
|
+
required=True, description="The name of the user who requested the proposed change to be reviewed"
|
|
155
|
+
)
|
|
156
|
+
payload = Field(GenericScalar, required=True)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class ProposedChangeMergedEvent(ObjectType):
|
|
160
|
+
class Meta:
|
|
161
|
+
interfaces = (EventNodeInterface,)
|
|
162
|
+
|
|
163
|
+
merged_by_account_id = String(required=True, description="The ID of the user who merged the proposed change")
|
|
164
|
+
merged_by_account_name = String(required=True, description="The name of the user who merged the proposed change")
|
|
165
|
+
payload = Field(GenericScalar, required=True)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class ProposedChangeThreadEvent(ObjectType):
|
|
169
|
+
class Meta:
|
|
170
|
+
interfaces = (EventNodeInterface,)
|
|
171
|
+
|
|
172
|
+
payload = Field(GenericScalar, required=True)
|
|
173
|
+
|
|
174
|
+
|
|
116
175
|
# ---------------------------------------
|
|
117
176
|
# Node/Object events
|
|
118
177
|
# ---------------------------------------
|
|
@@ -163,5 +222,14 @@ EVENT_TYPES: dict[str, type[ObjectType]] = {
|
|
|
163
222
|
events.BranchDeletedEvent.event_name: BranchDeletedEvent,
|
|
164
223
|
events.GroupMemberAddedEvent.event_name: GroupEvent,
|
|
165
224
|
events.GroupMemberRemovedEvent.event_name: GroupEvent,
|
|
225
|
+
events.ProposedChangeApprovedEvent.event_name: ProposedChangeReviewEvent,
|
|
226
|
+
events.ProposedChangeApprovalRevokedEvent.event_name: ProposedChangeReviewRevokedEvent,
|
|
227
|
+
events.ProposedChangeRejectedEvent.event_name: ProposedChangeReviewEvent,
|
|
228
|
+
events.ProposedChangeRejectionRevokedEvent.event_name: ProposedChangeReviewRevokedEvent,
|
|
229
|
+
events.ProposedChangeReviewRequestedEvent.event_name: ProposedChangeReviewRequestedEvent,
|
|
230
|
+
events.ProposedChangeApprovalsRevokedEvent.event_name: ProposedChangeApprovalsRevokedEvent,
|
|
231
|
+
events.ProposedChangeMergedEvent.event_name: ProposedChangeMergedEvent,
|
|
232
|
+
events.ProposedChangeThreadCreatedEvent.event_name: ProposedChangeThreadEvent,
|
|
233
|
+
events.ProposedChangeThreadUpdatedEvent.event_name: ProposedChangeThreadEvent,
|
|
166
234
|
"undefined": StandardEvent,
|
|
167
235
|
}
|
infrahub/groups/tasks.py
CHANGED
|
@@ -4,14 +4,16 @@ from prefect import flow
|
|
|
4
4
|
|
|
5
5
|
from infrahub.core.constants import InfrahubKind
|
|
6
6
|
from infrahub.groups.models import RequestGraphQLQueryGroupUpdate
|
|
7
|
-
from infrahub.
|
|
7
|
+
from infrahub.workers.dependencies import get_client
|
|
8
8
|
from infrahub.workflows.utils import add_tags
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
@flow(name="graphql-query-group-update", flow_run_name="Update GraphQLQuery Group '{model.query_name}'")
|
|
12
|
-
async def update_graphql_query_group(model: RequestGraphQLQueryGroupUpdate
|
|
12
|
+
async def update_graphql_query_group(model: RequestGraphQLQueryGroupUpdate) -> None:
|
|
13
13
|
"""Create or Update a GraphQLQueryGroup."""
|
|
14
14
|
|
|
15
|
+
client = get_client()
|
|
16
|
+
|
|
15
17
|
# If there is only one subscriber, associate the task to it
|
|
16
18
|
# If there are more than one, for now we can't associate all of them
|
|
17
19
|
related_nodes = []
|
|
@@ -23,7 +25,7 @@ async def update_graphql_query_group(model: RequestGraphQLQueryGroupUpdate, serv
|
|
|
23
25
|
params_hash = dict_hash(model.params)
|
|
24
26
|
group_name = f"{model.query_name}__{params_hash}"
|
|
25
27
|
group_label = f"Query {model.query_name} Hash({params_hash[:8]})"
|
|
26
|
-
group = await
|
|
28
|
+
group = await client.create(
|
|
27
29
|
kind=InfrahubKind.GRAPHQLQUERYGROUP,
|
|
28
30
|
branch=model.branch,
|
|
29
31
|
name=group_name,
|
|
@@ -36,6 +38,4 @@ async def update_graphql_query_group(model: RequestGraphQLQueryGroupUpdate, serv
|
|
|
36
38
|
await group.save(allow_upsert=True)
|
|
37
39
|
|
|
38
40
|
if model.subscribers:
|
|
39
|
-
await group_add_subscriber(
|
|
40
|
-
client=service.client, group=group, subscribers=model.subscribers, branch=model.branch
|
|
41
|
-
)
|
|
41
|
+
await group_add_subscriber(client=client, group=group, subscribers=model.subscribers, branch=model.branch)
|
infrahub/lock.py
CHANGED
|
@@ -12,6 +12,7 @@ from prometheus_client import Histogram
|
|
|
12
12
|
from redis.asyncio.lock import Lock as GlobalLock
|
|
13
13
|
|
|
14
14
|
from infrahub import config
|
|
15
|
+
from infrahub.core.timestamp import current_timestamp
|
|
15
16
|
|
|
16
17
|
if TYPE_CHECKING:
|
|
17
18
|
from types import TracebackType
|
|
@@ -91,7 +92,7 @@ class NATSLock:
|
|
|
91
92
|
await self.release()
|
|
92
93
|
|
|
93
94
|
async def acquire(self) -> None:
|
|
94
|
-
token =
|
|
95
|
+
token = current_timestamp()
|
|
95
96
|
while True:
|
|
96
97
|
if await self.do_acquire(token):
|
|
97
98
|
self.token = token
|
|
@@ -155,7 +156,7 @@ class InfrahubLock:
|
|
|
155
156
|
async def acquire(self) -> None:
|
|
156
157
|
with LOCK_ACQUIRE_TIME_METRICS.labels(self.name, self.lock_type).time():
|
|
157
158
|
if not self.use_local:
|
|
158
|
-
await self.remote.acquire()
|
|
159
|
+
await self.remote.acquire(token=current_timestamp())
|
|
159
160
|
else:
|
|
160
161
|
await self.local.acquire()
|
|
161
162
|
self.acquire_time = time.time_ns()
|
infrahub/menu/generator.py
CHANGED
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from infrahub.core import registry
|
|
6
|
+
from infrahub.core.constants import InfrahubKind
|
|
6
7
|
from infrahub.core.protocols import CoreMenuItem
|
|
7
8
|
from infrahub.log import get_logger
|
|
8
9
|
|
|
@@ -133,4 +134,11 @@ async def generate_menu(db: InfrahubDatabase, branch: Branch, menu_items: list[C
|
|
|
133
134
|
default_menu.children[str(menu_item.identifier)] = menu_item
|
|
134
135
|
items_to_add[item_name] = True
|
|
135
136
|
|
|
137
|
+
builtin_ipaddress = registry.schema.get_generic_schema(name=InfrahubKind.IPADDRESS, branch=branch, duplicate=False)
|
|
138
|
+
builtin_ipprefix = registry.schema.get_generic_schema(name=InfrahubKind.IPPREFIX, branch=branch, duplicate=False)
|
|
139
|
+
ipam_missing = len(builtin_ipaddress.used_by + builtin_ipprefix.used_by) == 0
|
|
140
|
+
|
|
141
|
+
if ipam_missing:
|
|
142
|
+
structure.data.pop("BuiltinIPAM")
|
|
143
|
+
|
|
136
144
|
return structure
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import ujson
|
|
2
2
|
from prefect import Flow
|
|
3
3
|
|
|
4
|
+
from infrahub.log import get_logger
|
|
4
5
|
from infrahub.message_bus import RPCErrorResponse, messages
|
|
5
|
-
from infrahub.message_bus.operations import
|
|
6
|
-
git,
|
|
7
|
-
refresh,
|
|
8
|
-
send,
|
|
9
|
-
)
|
|
6
|
+
from infrahub.message_bus.operations import git, refresh, send
|
|
10
7
|
from infrahub.message_bus.types import MessageTTL
|
|
11
|
-
from infrahub.services import
|
|
8
|
+
from infrahub.services.adapters.message_bus import InfrahubMessageBus
|
|
12
9
|
from infrahub.tasks.check import set_check_status
|
|
13
10
|
|
|
14
11
|
COMMAND_MAP = {
|
|
@@ -22,7 +19,7 @@ COMMAND_MAP = {
|
|
|
22
19
|
|
|
23
20
|
|
|
24
21
|
async def execute_message(
|
|
25
|
-
routing_key: str, message_body: bytes,
|
|
22
|
+
routing_key: str, message_body: bytes, message_bus: InfrahubMessageBus, skip_flow: bool = False
|
|
26
23
|
) -> MessageTTL | None:
|
|
27
24
|
message_data = ujson.loads(message_body)
|
|
28
25
|
message = messages.MESSAGE_MAP[routing_key](**message_data)
|
|
@@ -31,16 +28,16 @@ async def execute_message(
|
|
|
31
28
|
func = COMMAND_MAP[routing_key]
|
|
32
29
|
if skip_flow and isinstance(func, Flow):
|
|
33
30
|
func = func.fn
|
|
34
|
-
await func(message=message
|
|
31
|
+
await func(message=message)
|
|
35
32
|
except Exception as exc:
|
|
36
33
|
if message.reply_requested:
|
|
37
34
|
response = RPCErrorResponse(errors=[str(exc)], initial_message=message.model_dump())
|
|
38
|
-
await
|
|
35
|
+
await message_bus.reply_if_initiator_meta(message=response, initiator=message)
|
|
39
36
|
return None
|
|
40
37
|
if message.reached_max_retries:
|
|
41
|
-
|
|
42
|
-
await set_check_status(message, conclusion="failure"
|
|
38
|
+
get_logger().exception("Message failed after maximum number of retries", error=exc)
|
|
39
|
+
await set_check_status(message, conclusion="failure")
|
|
43
40
|
return None
|
|
44
41
|
message.increase_retry_count()
|
|
45
|
-
await
|
|
42
|
+
await message_bus.send(message, delay=MessageTTL.FIVE, is_retry=True)
|
|
46
43
|
return MessageTTL.FIVE
|
|
@@ -6,29 +6,30 @@ from infrahub.message_bus.messages.git_file_get import (
|
|
|
6
6
|
GitFileGetResponse,
|
|
7
7
|
GitFileGetResponseData,
|
|
8
8
|
)
|
|
9
|
-
from infrahub.
|
|
9
|
+
from infrahub.workers.dependencies import get_client, get_message_bus
|
|
10
10
|
|
|
11
11
|
log = get_logger()
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
async def get(message: messages.GitFileGet
|
|
14
|
+
async def get(message: messages.GitFileGet) -> None:
|
|
15
15
|
log.info("Collecting file from repository", repository=message.repository_name, file=message.file)
|
|
16
16
|
|
|
17
17
|
repo = await get_initialized_repo(
|
|
18
|
+
client=get_client(),
|
|
18
19
|
repository_id=message.repository_id,
|
|
19
20
|
name=message.repository_name,
|
|
20
|
-
service=service,
|
|
21
21
|
repository_kind=message.repository_kind,
|
|
22
22
|
commit=message.commit,
|
|
23
23
|
)
|
|
24
24
|
|
|
25
|
+
message_bus = await get_message_bus()
|
|
25
26
|
try:
|
|
26
27
|
content = await repo.get_file(commit=message.commit, location=message.file)
|
|
27
28
|
except (FileOutOfRepositoryError, RepositoryFileNotFoundError) as e:
|
|
28
29
|
if message.reply_requested:
|
|
29
30
|
response = GitFileGetResponse(data=GitFileGetResponseData(error_message=e.message, http_code=e.HTTP_CODE))
|
|
30
|
-
await
|
|
31
|
+
await message_bus.reply_if_initiator_meta(message=response, initiator=message)
|
|
31
32
|
else:
|
|
32
33
|
if message.reply_requested:
|
|
33
34
|
response = GitFileGetResponse(data=GitFileGetResponseData(content=content))
|
|
34
|
-
await
|
|
35
|
+
await message_bus.reply_if_initiator_meta(message=response, initiator=message)
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
from prefect import flow
|
|
2
2
|
|
|
3
3
|
from infrahub.exceptions import RepositoryError
|
|
4
|
-
from infrahub.git.repository import InfrahubRepository, get_initialized_repo
|
|
4
|
+
from infrahub.git.repository import InfrahubRepository, get_initialized_repo
|
|
5
5
|
from infrahub.log import get_logger
|
|
6
6
|
from infrahub.message_bus import messages
|
|
7
7
|
from infrahub.message_bus.messages.git_repository_connectivity import (
|
|
8
8
|
GitRepositoryConnectivityResponse,
|
|
9
9
|
GitRepositoryConnectivityResponseData,
|
|
10
10
|
)
|
|
11
|
-
from infrahub.services import InfrahubServices
|
|
12
11
|
from infrahub.worker import WORKER_IDENTITY
|
|
12
|
+
from infrahub.workers.dependencies import get_client, get_message_bus
|
|
13
13
|
|
|
14
14
|
log = get_logger()
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
@flow(name="git-repository-check-connectivity", flow_run_name="Check connectivity for {message.repository_name}")
|
|
18
|
-
async def connectivity(message: messages.GitRepositoryConnectivity
|
|
18
|
+
async def connectivity(message: messages.GitRepositoryConnectivity) -> None:
|
|
19
19
|
response_data = GitRepositoryConnectivityResponseData(message="Successfully accessed repository", success=True)
|
|
20
20
|
|
|
21
21
|
try:
|
|
@@ -28,30 +28,22 @@ async def connectivity(message: messages.GitRepositoryConnectivity, service: Inf
|
|
|
28
28
|
response = GitRepositoryConnectivityResponse(
|
|
29
29
|
data=response_data,
|
|
30
30
|
)
|
|
31
|
-
await
|
|
31
|
+
message_bus = await get_message_bus()
|
|
32
|
+
await message_bus.reply_if_initiator_meta(message=response, initiator=message)
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
@flow(name="refresh-git-fetch", flow_run_name="Fetch git repository {message.repository_name} on " + WORKER_IDENTITY)
|
|
35
|
-
async def fetch(message: messages.RefreshGitFetch
|
|
36
|
+
async def fetch(message: messages.RefreshGitFetch) -> None:
|
|
36
37
|
if message.meta and message.meta.initiator_id == WORKER_IDENTITY:
|
|
37
38
|
log.info("Ignoring git fetch request originating from self", worker=WORKER_IDENTITY)
|
|
38
39
|
return
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
)
|
|
47
|
-
except RepositoryError:
|
|
48
|
-
repo = await initialize_repo(
|
|
49
|
-
location=message.location,
|
|
50
|
-
repository_id=message.repository_id,
|
|
51
|
-
name=message.repository_name,
|
|
52
|
-
service=service,
|
|
53
|
-
repository_kind=message.repository_kind,
|
|
54
|
-
)
|
|
41
|
+
repo = await get_initialized_repo(
|
|
42
|
+
client=get_client(),
|
|
43
|
+
repository_id=message.repository_id,
|
|
44
|
+
name=message.repository_name,
|
|
45
|
+
repository_kind=message.repository_kind,
|
|
46
|
+
)
|
|
55
47
|
|
|
56
48
|
await repo.fetch()
|
|
57
49
|
await repo.pull(
|
|
@@ -1,28 +1,34 @@
|
|
|
1
|
+
from infrahub.log import get_logger
|
|
1
2
|
from infrahub.message_bus import messages
|
|
2
|
-
from infrahub.services import InfrahubServices
|
|
3
3
|
from infrahub.tasks.registry import refresh_branches
|
|
4
4
|
from infrahub.worker import WORKER_IDENTITY
|
|
5
|
+
from infrahub.workers.dependencies import get_component, get_database
|
|
5
6
|
|
|
6
7
|
|
|
7
|
-
async def branches(message: messages.RefreshRegistryBranches
|
|
8
|
+
async def branches(message: messages.RefreshRegistryBranches) -> None:
|
|
8
9
|
if message.meta and message.meta.initiator_id == WORKER_IDENTITY:
|
|
9
|
-
|
|
10
|
+
get_logger().info("Ignoring refresh registry refresh request originating from self", worker=WORKER_IDENTITY)
|
|
10
11
|
return
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
database = await get_database()
|
|
14
|
+
async with database.start_session(read_only=False) as db:
|
|
13
15
|
await refresh_branches(db=db)
|
|
14
16
|
|
|
15
|
-
await
|
|
17
|
+
component = await get_component()
|
|
18
|
+
await component.refresh_schema_hash()
|
|
16
19
|
|
|
17
20
|
|
|
18
|
-
async def rebased_branch(message: messages.RefreshRegistryRebasedBranch
|
|
21
|
+
async def rebased_branch(message: messages.RefreshRegistryRebasedBranch) -> None:
|
|
19
22
|
if message.meta and message.meta.initiator_id == WORKER_IDENTITY:
|
|
20
|
-
|
|
23
|
+
get_logger().info(
|
|
21
24
|
"Ignoring refresh registry refreshed branch for request originating from self", worker=WORKER_IDENTITY
|
|
22
25
|
)
|
|
23
26
|
return
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
database = await get_database()
|
|
29
|
+
|
|
30
|
+
async with database.start_session(read_only=True) as db:
|
|
26
31
|
await refresh_branches(db=db)
|
|
27
32
|
|
|
28
|
-
await
|
|
33
|
+
component = await get_component()
|
|
34
|
+
await component.refresh_schema_hash()
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
from prefect import flow
|
|
2
2
|
|
|
3
|
+
from infrahub.log import get_logger
|
|
3
4
|
from infrahub.message_bus import messages
|
|
4
5
|
from infrahub.message_bus.messages.send_echo_request import SendEchoRequestResponse, SendEchoRequestResponseData
|
|
5
|
-
from infrahub.
|
|
6
|
+
from infrahub.workers.dependencies import get_message_bus
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
@flow(name="echo-request")
|
|
9
|
-
async def request(message: messages.SendEchoRequest
|
|
10
|
-
|
|
10
|
+
async def request(message: messages.SendEchoRequest) -> None:
|
|
11
|
+
get_logger().info(f"Received message: {message.message}")
|
|
12
|
+
|
|
11
13
|
if message.reply_requested:
|
|
12
14
|
response = SendEchoRequestResponse(data=SendEchoRequestResponseData(response=f"Reply to: {message.message}"))
|
|
13
|
-
await
|
|
15
|
+
message_bus = await get_message_bus()
|
|
16
|
+
await message_bus.reply_if_initiator_meta(message=response, initiator=message)
|
infrahub/message_bus/types.py
CHANGED
infrahub/permissions/__init__.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from infrahub.permissions.backend import PermissionBackend
|
|
2
|
-
from infrahub.permissions.globals import define_global_permission_from_branch
|
|
2
|
+
from infrahub.permissions.globals import define_global_permission_from_branch, get_or_create_global_permission
|
|
3
3
|
from infrahub.permissions.local_backend import LocalPermissionBackend
|
|
4
4
|
from infrahub.permissions.manager import PermissionManager
|
|
5
5
|
from infrahub.permissions.report import report_schema_permissions
|
|
@@ -12,5 +12,6 @@ __all__ = [
|
|
|
12
12
|
"PermissionManager",
|
|
13
13
|
"define_global_permission_from_branch",
|
|
14
14
|
"get_global_permission_for_kind",
|
|
15
|
+
"get_or_create_global_permission",
|
|
15
16
|
"report_schema_permissions",
|
|
16
17
|
]
|
|
@@ -25,8 +25,21 @@ GLOBAL_PERMISSION_DENIAL_MESSAGE = {
|
|
|
25
25
|
GlobalPermissions.EDIT_DEFAULT_BRANCH.value: "You are not allowed to change data in the default branch",
|
|
26
26
|
GlobalPermissions.MERGE_BRANCH.value: "You are not allowed to merge a branch",
|
|
27
27
|
GlobalPermissions.MERGE_PROPOSED_CHANGE.value: "You are not allowed to merge proposed changes",
|
|
28
|
+
GlobalPermissions.REVIEW_PROPOSED_CHANGE.value: "You are not allowed to review proposed changes",
|
|
28
29
|
GlobalPermissions.MANAGE_SCHEMA.value: "You are not allowed to manage the schema",
|
|
29
30
|
GlobalPermissions.MANAGE_ACCOUNTS.value: "You are not allowed to manage user accounts, groups or roles",
|
|
30
31
|
GlobalPermissions.MANAGE_PERMISSIONS.value: "You are not allowed to manage permissions",
|
|
31
32
|
GlobalPermissions.MANAGE_REPOSITORIES.value: "You are not allowed to manage repositories",
|
|
32
33
|
}
|
|
34
|
+
|
|
35
|
+
GLOBAL_PERMISSION_DESCRIPTION = {
|
|
36
|
+
GlobalPermissions.EDIT_DEFAULT_BRANCH: "Allow a user to change data in the default branch",
|
|
37
|
+
GlobalPermissions.MERGE_BRANCH: "Allow a user to merge branches",
|
|
38
|
+
GlobalPermissions.MERGE_PROPOSED_CHANGE: "Allow a user to merge proposed changes",
|
|
39
|
+
GlobalPermissions.REVIEW_PROPOSED_CHANGE: "Allow a user to approve or reject proposed changes",
|
|
40
|
+
GlobalPermissions.MANAGE_SCHEMA: "Allow a user to manage the schema",
|
|
41
|
+
GlobalPermissions.MANAGE_ACCOUNTS: "Allow a user to manage accounts, account roles and account groups",
|
|
42
|
+
GlobalPermissions.MANAGE_PERMISSIONS: "Allow a user to manage permissions",
|
|
43
|
+
GlobalPermissions.MANAGE_REPOSITORIES: "Allow a user to manage repositories",
|
|
44
|
+
GlobalPermissions.SUPER_ADMIN: "Allow a user to do anything",
|
|
45
|
+
}
|
infrahub/permissions/globals.py
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
1
5
|
from infrahub.core.account import GlobalPermission
|
|
2
6
|
from infrahub.core.constants import GLOBAL_BRANCH_NAME, GlobalPermissions, PermissionDecision
|
|
7
|
+
from infrahub.core.manager import NodeManager
|
|
8
|
+
from infrahub.core.node import Node
|
|
9
|
+
from infrahub.core.protocols import CoreGlobalPermission
|
|
3
10
|
from infrahub.core.registry import registry
|
|
4
11
|
|
|
12
|
+
from .constants import GLOBAL_PERMISSION_DESCRIPTION
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from infrahub.database import InfrahubDatabase
|
|
16
|
+
|
|
5
17
|
|
|
6
18
|
def define_global_permission_from_branch(permission: GlobalPermissions, branch_name: str) -> GlobalPermission:
|
|
7
19
|
if branch_name in (GLOBAL_BRANCH_NAME, registry.default_branch):
|
|
@@ -9,7 +21,24 @@ def define_global_permission_from_branch(permission: GlobalPermissions, branch_n
|
|
|
9
21
|
else:
|
|
10
22
|
decision = PermissionDecision.ALLOW_OTHER
|
|
11
23
|
|
|
12
|
-
return GlobalPermission(
|
|
24
|
+
return GlobalPermission(action=permission.value, decision=decision.value)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
async def get_or_create_global_permission(db: InfrahubDatabase, permission: GlobalPermissions) -> CoreGlobalPermission:
|
|
28
|
+
permissions = await NodeManager.query(
|
|
29
|
+
db=db, schema=CoreGlobalPermission, filters={"action__value": permission.value}, limit=1
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
if permissions:
|
|
33
|
+
return permissions[0]
|
|
34
|
+
|
|
35
|
+
p = await Node.init(db=db, schema=CoreGlobalPermission)
|
|
36
|
+
await p.new(
|
|
37
|
+
db=db,
|
|
13
38
|
action=permission.value,
|
|
14
|
-
decision=
|
|
39
|
+
decision=PermissionDecision.ALLOW_ALL.value,
|
|
40
|
+
description=GLOBAL_PERMISSION_DESCRIPTION[permission],
|
|
15
41
|
)
|
|
42
|
+
await p.save(db=db)
|
|
43
|
+
|
|
44
|
+
return p
|