infrahub-server 1.1.6__py3-none-any.whl → 1.1.8__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/core/attribute.py +4 -1
- infrahub/core/branch/tasks.py +7 -4
- infrahub/core/diff/combiner.py +11 -7
- infrahub/core/diff/coordinator.py +49 -70
- infrahub/core/diff/data_check_synchronizer.py +86 -7
- infrahub/core/diff/enricher/aggregated.py +3 -3
- infrahub/core/diff/enricher/cardinality_one.py +6 -6
- infrahub/core/diff/enricher/hierarchy.py +17 -4
- infrahub/core/diff/enricher/labels.py +18 -3
- infrahub/core/diff/enricher/path_identifier.py +7 -8
- infrahub/core/diff/merger/merger.py +5 -3
- infrahub/core/diff/model/path.py +66 -25
- infrahub/core/diff/parent_node_adder.py +78 -0
- infrahub/core/diff/payload_builder.py +13 -2
- infrahub/core/diff/query/all_conflicts.py +5 -2
- infrahub/core/diff/query/diff_get.py +2 -1
- infrahub/core/diff/query/field_specifiers.py +2 -0
- infrahub/core/diff/query/field_summary.py +2 -1
- infrahub/core/diff/query/filters.py +12 -1
- infrahub/core/diff/query/has_conflicts_query.py +5 -2
- infrahub/core/diff/query/{drop_tracking_id.py → merge_tracking_id.py} +3 -3
- infrahub/core/diff/query/roots_metadata.py +8 -1
- infrahub/core/diff/query/save.py +230 -139
- infrahub/core/diff/query/summary_counts_enricher.py +267 -0
- infrahub/core/diff/query/time_range_query.py +2 -1
- infrahub/core/diff/query_parser.py +49 -24
- infrahub/core/diff/repository/deserializer.py +31 -27
- infrahub/core/diff/repository/repository.py +215 -41
- infrahub/core/diff/tasks.py +4 -4
- infrahub/core/graph/__init__.py +1 -1
- infrahub/core/graph/index.py +3 -0
- infrahub/core/migrations/graph/__init__.py +4 -0
- infrahub/core/migrations/graph/m019_restore_rels_to_time.py +256 -0
- infrahub/core/migrations/graph/m020_duplicate_edges.py +160 -0
- infrahub/core/migrations/query/node_duplicate.py +38 -18
- infrahub/core/migrations/schema/node_remove.py +26 -12
- infrahub/core/migrations/shared.py +10 -8
- infrahub/core/node/__init__.py +19 -9
- infrahub/core/node/constraints/grouped_uniqueness.py +25 -5
- infrahub/core/node/ipam.py +6 -1
- infrahub/core/node/permissions.py +4 -0
- infrahub/core/query/attribute.py +2 -0
- infrahub/core/query/diff.py +41 -3
- infrahub/core/query/node.py +74 -21
- infrahub/core/query/relationship.py +107 -17
- infrahub/core/query/resource_manager.py +5 -1
- infrahub/core/relationship/model.py +8 -12
- infrahub/core/schema/definitions/core.py +1 -0
- infrahub/core/utils.py +1 -0
- infrahub/core/validators/uniqueness/query.py +20 -17
- infrahub/database/__init__.py +14 -0
- infrahub/dependencies/builder/constraint/grouped/node_runner.py +0 -2
- infrahub/dependencies/builder/diff/coordinator.py +0 -2
- infrahub/dependencies/builder/diff/deserializer.py +3 -1
- infrahub/dependencies/builder/diff/enricher/hierarchy.py +3 -1
- infrahub/dependencies/builder/diff/parent_node_adder.py +8 -0
- infrahub/graphql/mutations/computed_attribute.py +3 -1
- infrahub/graphql/mutations/diff.py +41 -10
- infrahub/graphql/mutations/main.py +11 -6
- infrahub/graphql/mutations/relationship.py +29 -1
- infrahub/graphql/mutations/resource_manager.py +3 -3
- infrahub/graphql/mutations/tasks.py +6 -3
- infrahub/graphql/queries/resource_manager.py +7 -3
- infrahub/permissions/__init__.py +2 -1
- infrahub/permissions/types.py +26 -0
- infrahub_sdk/client.py +10 -2
- infrahub_sdk/config.py +3 -0
- infrahub_sdk/ctl/check.py +3 -3
- infrahub_sdk/ctl/cli_commands.py +16 -11
- infrahub_sdk/ctl/exceptions.py +0 -6
- infrahub_sdk/ctl/exporter.py +1 -1
- infrahub_sdk/ctl/generator.py +5 -5
- infrahub_sdk/ctl/importer.py +3 -2
- infrahub_sdk/ctl/menu.py +1 -1
- infrahub_sdk/ctl/object.py +1 -1
- infrahub_sdk/ctl/repository.py +23 -15
- infrahub_sdk/ctl/schema.py +2 -2
- infrahub_sdk/ctl/utils.py +4 -3
- infrahub_sdk/ctl/validate.py +2 -1
- infrahub_sdk/exceptions.py +12 -0
- infrahub_sdk/generator.py +3 -0
- infrahub_sdk/node.py +7 -4
- infrahub_sdk/testing/schemas/animal.py +9 -0
- infrahub_sdk/utils.py +11 -1
- infrahub_sdk/yaml.py +2 -3
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.1.8.dist-info}/METADATA +41 -7
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.1.8.dist-info}/RECORD +94 -91
- infrahub_testcontainers/container.py +12 -3
- infrahub_testcontainers/docker-compose.test.yml +22 -3
- infrahub_testcontainers/haproxy.cfg +43 -0
- infrahub_testcontainers/helpers.py +85 -1
- infrahub/core/diff/enricher/summary_counts.py +0 -105
- infrahub/dependencies/builder/diff/enricher/summary_counts.py +0 -8
- infrahub_sdk/ctl/_file.py +0 -13
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.1.8.dist-info}/LICENSE.txt +0 -0
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.1.8.dist-info}/WHEEL +0 -0
- {infrahub_server-1.1.6.dist-info → infrahub_server-1.1.8.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
global
|
|
2
|
+
log stdout local0
|
|
3
|
+
log stdout local1 notice
|
|
4
|
+
#chroot /var/lib/haproxy
|
|
5
|
+
#stats socket /run/haproxy/admin.sock mode 660 level admin
|
|
6
|
+
stats timeout 30s
|
|
7
|
+
user haproxy
|
|
8
|
+
group haproxy
|
|
9
|
+
daemon
|
|
10
|
+
|
|
11
|
+
# Default SSL material locations
|
|
12
|
+
ca-base /etc/ssl/certs
|
|
13
|
+
crt-base /etc/ssl/private
|
|
14
|
+
|
|
15
|
+
# See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
|
|
16
|
+
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
|
17
|
+
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
|
|
18
|
+
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
|
|
19
|
+
|
|
20
|
+
defaults
|
|
21
|
+
log global
|
|
22
|
+
mode http
|
|
23
|
+
option httplog
|
|
24
|
+
option dontlognull
|
|
25
|
+
timeout connect 5000
|
|
26
|
+
timeout client 50000
|
|
27
|
+
timeout server 50000
|
|
28
|
+
|
|
29
|
+
resolvers docker
|
|
30
|
+
parse-resolv-conf
|
|
31
|
+
accepted_payload_size 8192
|
|
32
|
+
|
|
33
|
+
frontend fe
|
|
34
|
+
mode http
|
|
35
|
+
bind *:8000
|
|
36
|
+
option forwardfor
|
|
37
|
+
|
|
38
|
+
default_backend be
|
|
39
|
+
|
|
40
|
+
backend be
|
|
41
|
+
mode http
|
|
42
|
+
balance roundrobin
|
|
43
|
+
server-template api 100 infrahub-server:8000 check resolvers docker init-addr none
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import shutil
|
|
2
3
|
import subprocess # noqa: S404
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
|
|
@@ -36,12 +37,25 @@ class TestInfrahubDocker:
|
|
|
36
37
|
|
|
37
38
|
return directory
|
|
38
39
|
|
|
40
|
+
@pytest.fixture(scope="class")
|
|
41
|
+
def remote_backups_dir(self, tmp_directory: Path) -> Path:
|
|
42
|
+
directory = tmp_directory / PROJECT_ENV_VARIABLES["INFRAHUB_TESTING_LOCAL_DB_BACKUP_DIRECTORY"]
|
|
43
|
+
directory.mkdir(exist_ok=True)
|
|
44
|
+
|
|
45
|
+
return directory
|
|
46
|
+
|
|
39
47
|
@pytest.fixture(scope="class")
|
|
40
48
|
def default_branch(self) -> str:
|
|
41
49
|
return "main"
|
|
42
50
|
|
|
43
51
|
@pytest.fixture(scope="class")
|
|
44
|
-
def infrahub_compose(
|
|
52
|
+
def infrahub_compose(
|
|
53
|
+
self,
|
|
54
|
+
tmp_directory: Path,
|
|
55
|
+
remote_repos_dir: Path, # initialize repository before running docker compose to fix permissions issues # noqa: ARG002
|
|
56
|
+
remote_backups_dir: Path, # noqa: ARG002
|
|
57
|
+
infrahub_version: str,
|
|
58
|
+
) -> InfrahubDockerCompose:
|
|
45
59
|
return InfrahubDockerCompose.init(directory=tmp_directory, version=infrahub_version)
|
|
46
60
|
|
|
47
61
|
@pytest.fixture(scope="class")
|
|
@@ -62,3 +76,73 @@ class TestInfrahubDocker:
|
|
|
62
76
|
@pytest.fixture(scope="class")
|
|
63
77
|
def task_manager_port(self, infrahub_app: dict[str, int]) -> int:
|
|
64
78
|
return infrahub_app["task-manager"]
|
|
79
|
+
|
|
80
|
+
def backup_database(self, request: pytest.FixtureRequest, dest_dir: Path | None = None) -> None:
|
|
81
|
+
assert "enterprise" in os.environ.get("NEO4J_DOCKER_IMAGE", "")
|
|
82
|
+
|
|
83
|
+
backup_dir: Path = request.getfixturevalue("remote_backups_dir")
|
|
84
|
+
infrahub_compose: InfrahubDockerCompose = request.getfixturevalue("infrahub_compose")
|
|
85
|
+
|
|
86
|
+
infrahub_compose.exec_in_container(
|
|
87
|
+
command=[
|
|
88
|
+
"neo4j-admin",
|
|
89
|
+
"database",
|
|
90
|
+
"backup",
|
|
91
|
+
"--to-path",
|
|
92
|
+
os.environ.get(
|
|
93
|
+
"INFRAHUB_TESTING_INTERNAL_DB_BACKUP_DIRECTORY",
|
|
94
|
+
PROJECT_ENV_VARIABLES["INFRAHUB_TESTING_INTERNAL_DB_BACKUP_DIRECTORY"],
|
|
95
|
+
),
|
|
96
|
+
],
|
|
97
|
+
service_name="database",
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
if dest_dir:
|
|
101
|
+
shutil.copytree(
|
|
102
|
+
str(backup_dir),
|
|
103
|
+
str(dest_dir),
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
def restore_database(self, request: pytest.FixtureRequest, backup_file: Path) -> None:
|
|
107
|
+
assert "enterprise" in os.environ.get("NEO4J_DOCKER_IMAGE", "")
|
|
108
|
+
|
|
109
|
+
backup_dir: Path = request.getfixturevalue("remote_backups_dir")
|
|
110
|
+
infrahub_compose: InfrahubDockerCompose = request.getfixturevalue("infrahub_compose")
|
|
111
|
+
|
|
112
|
+
shutil.copy(
|
|
113
|
+
str(backup_file),
|
|
114
|
+
str(backup_dir / backup_file.name),
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
infrahub_compose.exec_in_container(
|
|
118
|
+
command=["cypher-shell", "-u", "neo4j", "-p", "admin", "STOP DATABASE neo4j;"],
|
|
119
|
+
service_name="database",
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
infrahub_compose.exec_in_container(
|
|
123
|
+
command=[
|
|
124
|
+
"neo4j-admin",
|
|
125
|
+
"database",
|
|
126
|
+
"restore",
|
|
127
|
+
"--overwrite-destination",
|
|
128
|
+
"--from-path",
|
|
129
|
+
str(
|
|
130
|
+
Path(
|
|
131
|
+
os.environ.get(
|
|
132
|
+
"INFRAHUB_TESTING_INTERNAL_DB_BACKUP_DIRECTORY",
|
|
133
|
+
PROJECT_ENV_VARIABLES["INFRAHUB_TESTING_INTERNAL_DB_BACKUP_DIRECTORY"],
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
/ backup_file.name
|
|
137
|
+
),
|
|
138
|
+
],
|
|
139
|
+
service_name="database",
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
infrahub_compose.exec_in_container(
|
|
143
|
+
command=["cypher-shell", "-d", "system", "-u", "neo4j", "-p", "admin", "START DATABASE neo4j;"],
|
|
144
|
+
service_name="database",
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
infrahub_compose.stop(down=False)
|
|
148
|
+
infrahub_compose.start()
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
from collections import Counter
|
|
2
|
-
from typing import Iterable
|
|
3
|
-
|
|
4
|
-
from infrahub.core.constants import DiffAction
|
|
5
|
-
|
|
6
|
-
from ..model.path import (
|
|
7
|
-
BaseSummary,
|
|
8
|
-
CalculatedDiffs,
|
|
9
|
-
EnrichedDiffAttribute,
|
|
10
|
-
EnrichedDiffNode,
|
|
11
|
-
EnrichedDiffRelationship,
|
|
12
|
-
EnrichedDiffRoot,
|
|
13
|
-
EnrichedDiffSingleRelationship,
|
|
14
|
-
)
|
|
15
|
-
from .interface import DiffEnricherInterface
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class DiffSummaryCountsEnricher(DiffEnricherInterface):
|
|
19
|
-
async def enrich(
|
|
20
|
-
self, enriched_diff_root: EnrichedDiffRoot, calculated_diffs: CalculatedDiffs | None = None
|
|
21
|
-
) -> None:
|
|
22
|
-
self._add_root_summaries(diff_root=enriched_diff_root)
|
|
23
|
-
|
|
24
|
-
def _add_summary(self, summary_node: BaseSummary, actions: Iterable[DiffAction]) -> None:
|
|
25
|
-
summary_count = Counter(actions)
|
|
26
|
-
summary_node.num_added = summary_count.get(DiffAction.ADDED, 0)
|
|
27
|
-
summary_node.num_updated = summary_count.get(DiffAction.UPDATED, 0)
|
|
28
|
-
summary_node.num_removed = summary_count.get(DiffAction.REMOVED, 0)
|
|
29
|
-
|
|
30
|
-
def _add_root_summaries(self, diff_root: EnrichedDiffRoot) -> None:
|
|
31
|
-
contains_conflict = False
|
|
32
|
-
num_conflicts = 0
|
|
33
|
-
for diff_node in diff_root.nodes:
|
|
34
|
-
contains_conflict |= self._add_node_summaries(diff_node=diff_node)
|
|
35
|
-
if diff_node.conflict or diff_node.contains_conflict:
|
|
36
|
-
num_conflicts += 1
|
|
37
|
-
self._add_summary(summary_node=diff_root, actions=(n.action for n in diff_root.nodes))
|
|
38
|
-
diff_root.contains_conflict = contains_conflict
|
|
39
|
-
diff_root.num_conflicts = num_conflicts
|
|
40
|
-
self._add_child_nodes_to_summaries(diff_root=diff_root)
|
|
41
|
-
|
|
42
|
-
def _add_node_summaries(self, diff_node: EnrichedDiffNode) -> bool:
|
|
43
|
-
contains_conflict = False
|
|
44
|
-
num_conflicts = 0
|
|
45
|
-
for diff_attr in diff_node.attributes:
|
|
46
|
-
contains_conflict |= self._add_attribute_summaries(diff_attribute=diff_attr)
|
|
47
|
-
if diff_attr.contains_conflict:
|
|
48
|
-
num_conflicts += 1
|
|
49
|
-
for diff_rel in diff_node.relationships:
|
|
50
|
-
contains_conflict |= self._add_relationship_summaries(diff_relationship=diff_rel)
|
|
51
|
-
if diff_rel.contains_conflict:
|
|
52
|
-
num_conflicts += 1
|
|
53
|
-
self._add_summary(
|
|
54
|
-
summary_node=diff_node, actions=(field.action for field in diff_node.relationships | diff_node.attributes)
|
|
55
|
-
)
|
|
56
|
-
diff_node.contains_conflict = contains_conflict
|
|
57
|
-
diff_node.num_conflicts = num_conflicts
|
|
58
|
-
return contains_conflict
|
|
59
|
-
|
|
60
|
-
def _add_attribute_summaries(self, diff_attribute: EnrichedDiffAttribute) -> bool:
|
|
61
|
-
contains_conflict = False
|
|
62
|
-
num_conflicts = 0
|
|
63
|
-
for diff_prop in diff_attribute.properties:
|
|
64
|
-
if diff_prop.conflict:
|
|
65
|
-
num_conflicts += 1
|
|
66
|
-
contains_conflict = True
|
|
67
|
-
self._add_summary(summary_node=diff_attribute, actions=(p.action for p in diff_attribute.properties))
|
|
68
|
-
diff_attribute.contains_conflict = contains_conflict
|
|
69
|
-
diff_attribute.num_conflicts = num_conflicts
|
|
70
|
-
return contains_conflict
|
|
71
|
-
|
|
72
|
-
def _add_relationship_summaries(self, diff_relationship: EnrichedDiffRelationship) -> bool:
|
|
73
|
-
contains_conflict = False
|
|
74
|
-
num_conflicts = 0
|
|
75
|
-
for diff_element in diff_relationship.relationships:
|
|
76
|
-
contains_conflict |= self._add_element_summaries(diff_element=diff_element)
|
|
77
|
-
if diff_element.conflict:
|
|
78
|
-
num_conflicts += 1
|
|
79
|
-
self._add_summary(summary_node=diff_relationship, actions=(e.action for e in diff_relationship.relationships))
|
|
80
|
-
diff_relationship.contains_conflict = contains_conflict
|
|
81
|
-
diff_relationship.num_conflicts = num_conflicts
|
|
82
|
-
return contains_conflict
|
|
83
|
-
|
|
84
|
-
def _add_element_summaries(self, diff_element: EnrichedDiffSingleRelationship) -> bool:
|
|
85
|
-
if diff_element.conflict is None:
|
|
86
|
-
contains_conflict = False
|
|
87
|
-
num_conflicts = 0
|
|
88
|
-
else:
|
|
89
|
-
contains_conflict = True
|
|
90
|
-
num_conflicts = 1
|
|
91
|
-
for diff_prop in diff_element.properties:
|
|
92
|
-
if diff_prop.conflict:
|
|
93
|
-
num_conflicts += 1
|
|
94
|
-
contains_conflict = True
|
|
95
|
-
self._add_summary(summary_node=diff_element, actions=(p.action for p in diff_element.properties))
|
|
96
|
-
diff_element.contains_conflict = contains_conflict
|
|
97
|
-
diff_element.num_conflicts = num_conflicts
|
|
98
|
-
return contains_conflict
|
|
99
|
-
|
|
100
|
-
def _add_child_nodes_to_summaries(self, diff_root: EnrichedDiffRoot) -> None:
|
|
101
|
-
for diff_node in diff_root.nodes:
|
|
102
|
-
for diff_rel in diff_node.relationships:
|
|
103
|
-
if not diff_rel.contains_conflict:
|
|
104
|
-
diff_rel.contains_conflict = any(n.contains_conflict for n in diff_rel.nodes)
|
|
105
|
-
diff_rel.num_conflicts += sum(bool(n.contains_conflict or n.conflict) for n in diff_rel.nodes)
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
from infrahub.core.diff.enricher.summary_counts import DiffSummaryCountsEnricher
|
|
2
|
-
from infrahub.dependencies.interface import DependencyBuilder, DependencyBuilderContext
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class DiffSummaryCountsEnricherDependency(DependencyBuilder[DiffSummaryCountsEnricher]):
|
|
6
|
-
@classmethod
|
|
7
|
-
def build(cls, context: DependencyBuilderContext) -> DiffSummaryCountsEnricher:
|
|
8
|
-
return DiffSummaryCountsEnricher()
|
infrahub_sdk/ctl/_file.py
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
|
|
3
|
-
from .exceptions import FileNotValidError
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def read_file(file_name: Path) -> str:
|
|
7
|
-
if not file_name.is_file():
|
|
8
|
-
raise FileNotValidError(name=str(file_name), message=f"{file_name} is not a valid file")
|
|
9
|
-
try:
|
|
10
|
-
with Path.open(file_name, encoding="utf-8") as fobj:
|
|
11
|
-
return fobj.read()
|
|
12
|
-
except UnicodeDecodeError as exc:
|
|
13
|
-
raise FileNotValidError(name=str(file_name), message=f"Unable to read {file_name} with utf-8 encoding") from exc
|
|
File without changes
|
|
File without changes
|
|
File without changes
|