atlas-init 0.3.1__py3-none-any.whl → 0.3.2__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.
- atlas_init/__init__.py +1 -1
- atlas_init/cli_tf/debug_logs.py +6 -6
- atlas_init/cli_tf/debug_logs_test_data.py +7 -7
- atlas_init/cli_tf/mock_tf_log.py +58 -6
- {atlas_init-0.3.1.dist-info → atlas_init-0.3.2.dist-info}/METADATA +1 -1
- {atlas_init-0.3.1.dist-info → atlas_init-0.3.2.dist-info}/RECORD +8 -8
- {atlas_init-0.3.1.dist-info → atlas_init-0.3.2.dist-info}/WHEEL +0 -0
- {atlas_init-0.3.1.dist-info → atlas_init-0.3.2.dist-info}/entry_points.txt +0 -0
atlas_init/__init__.py
CHANGED
atlas_init/cli_tf/debug_logs.py
CHANGED
@@ -98,12 +98,12 @@ class SDKRoundtrip(Entity):
|
|
98
98
|
@property
|
99
99
|
def version(self) -> str:
|
100
100
|
content_type = self.response.headers.get("Content-Type", "v1")
|
101
|
-
|
101
|
+
content_type_req = self.request.headers.get("Accept", "v1")
|
102
|
+
with suppress(ValueError):
|
102
103
|
return extract_version(content_type)
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
return extract_version(content_type)
|
104
|
+
with suppress(ValueError):
|
105
|
+
return extract_version(content_type_req)
|
106
|
+
raise ValueError(f"Could not extract version from req/resp: {content_type} or {content_type_req}")
|
107
107
|
|
108
108
|
@model_validator(mode="after")
|
109
109
|
def ensure_match(self) -> Self:
|
@@ -159,7 +159,7 @@ def parse_http_requests(logs: str) -> list[SDKRoundtrip]:
|
|
159
159
|
Can say that expected payload is either a list or a dict and if it ends with an identifier it is higher chance for a dict
|
160
160
|
"""
|
161
161
|
test_name = parse_test_name(logs)
|
162
|
-
logger.info(f"Finding http requests for test name: {test_name}")
|
162
|
+
logger.info(f"Finding http requests for test name: '{test_name}'")
|
163
163
|
requests, responses = parse_raw_req_responses(logs)
|
164
164
|
tf_step_starts = [i for i, line in enumerate(logs.splitlines()) if MARKER_START_STEP in line]
|
165
165
|
used_responses: set[int] = set()
|
@@ -31,7 +31,7 @@ class RequestInfo(Entity):
|
|
31
31
|
|
32
32
|
@property
|
33
33
|
def id(self):
|
34
|
-
return "__".join((self.method, self.path, self.version, self.text)
|
34
|
+
return "__".join(part for part in (self.method, self.path, self.version, self.text) if part)
|
35
35
|
|
36
36
|
|
37
37
|
class StepRequests(Entity):
|
@@ -143,9 +143,9 @@ class MockRequestData(Entity):
|
|
143
143
|
def replace_text_variables(self):
|
144
144
|
for step in self.steps:
|
145
145
|
for request in step.all_requests:
|
146
|
-
request.text = normalize_text(request.text, self.variables)
|
146
|
+
request.text = normalize_text(request.text, self.variables, expect_json=True)
|
147
147
|
for response in request.responses:
|
148
|
-
response.text = normalize_text(response.text, self.variables)
|
148
|
+
response.text = normalize_text(response.text, self.variables, expect_json=True)
|
149
149
|
|
150
150
|
def prune_duplicate_responses(self):
|
151
151
|
for step in self.steps:
|
@@ -202,10 +202,10 @@ def find_normalized_path(path: str, api_spec_paths: list[ApiSpecPath]) -> ApiSpe
|
|
202
202
|
raise ValueError(f"Could not find path: {path}")
|
203
203
|
|
204
204
|
|
205
|
-
def normalize_text(text: str, variables: dict[str, str]) -> str:
|
205
|
+
def normalize_text(text: str, variables: dict[str, str], *, expect_json: bool = False) -> str:
|
206
206
|
for var, value in variables.items():
|
207
207
|
text = text.replace(value, f"{{{var}}}")
|
208
|
-
if not text:
|
208
|
+
if not text or not expect_json:
|
209
209
|
return text
|
210
210
|
try:
|
211
211
|
parsed_text = json.loads(text)
|
@@ -260,8 +260,8 @@ def create_mock_data(
|
|
260
260
|
for modifier in modifiers:
|
261
261
|
if modifier.match(rt, normalized_path):
|
262
262
|
modifier.modification(rt)
|
263
|
-
normalized_text = normalize_text(rt.request.text, mock_data.variables)
|
264
|
-
normalized_response_text = normalize_text(rt.response.text, mock_data.variables)
|
263
|
+
normalized_text = normalize_text(rt.request.text, mock_data.variables, expect_json=True)
|
264
|
+
normalized_response_text = normalize_text(rt.response.text, mock_data.variables, expect_json=True)
|
265
265
|
mock_data.add_roundtrip(rt, normalized_path, normalized_text, normalized_response_text, is_diff(rt))
|
266
266
|
mock_data.replace_text_variables()
|
267
267
|
if prune_duplicates:
|
atlas_init/cli_tf/mock_tf_log.py
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
import json
|
2
2
|
import logging
|
3
3
|
import time
|
4
|
+
from collections.abc import Callable
|
5
|
+
from io import StringIO
|
4
6
|
from pathlib import Path
|
5
7
|
from typing import Self
|
6
8
|
|
7
9
|
import typer
|
8
|
-
|
10
|
+
import yaml
|
11
|
+
from model_lib import Entity
|
9
12
|
from pydantic import Field, model_validator
|
10
13
|
from zero_3rdparty import file_utils
|
11
14
|
|
@@ -15,8 +18,16 @@ from atlas_init.cli_tf.debug_logs import (
|
|
15
18
|
parse_http_requests,
|
16
19
|
parse_test_name,
|
17
20
|
)
|
18
|
-
from atlas_init.cli_tf.debug_logs_test_data import
|
19
|
-
|
21
|
+
from atlas_init.cli_tf.debug_logs_test_data import (
|
22
|
+
RTModifier,
|
23
|
+
create_mock_data,
|
24
|
+
default_is_diff,
|
25
|
+
)
|
26
|
+
from atlas_init.repos.go_sdk import (
|
27
|
+
api_spec_path_transformed,
|
28
|
+
download_admin_api,
|
29
|
+
parse_api_spec_paths,
|
30
|
+
)
|
20
31
|
from atlas_init.settings.path import DEFAULT_DOWNLOADS_DIR
|
21
32
|
|
22
33
|
logger = logging.getLogger(__name__)
|
@@ -28,6 +39,8 @@ class MockTFLog(Entity):
|
|
28
39
|
admin_api_path: Path
|
29
40
|
diff_skip_suffixes: list[str] = Field(default_factory=list)
|
30
41
|
keep_duplicates: bool = False
|
42
|
+
modifiers: list[RTModifier] = Field(default_factory=list)
|
43
|
+
log_diff_roundtrips: bool = False
|
31
44
|
|
32
45
|
@model_validator(mode="after")
|
33
46
|
def ensure_paths_exist(self) -> Self:
|
@@ -44,22 +57,40 @@ class MockTFLog(Entity):
|
|
44
57
|
return default_is_diff(rt) and not any(rt.request.path.endswith(suffix) for suffix in self.diff_skip_suffixes)
|
45
58
|
|
46
59
|
|
47
|
-
def mock_tf_log(req: MockTFLog) ->
|
60
|
+
def mock_tf_log(req: MockTFLog) -> Path:
|
48
61
|
log_file_text = req.log_path.read_text()
|
49
62
|
test_name = parse_test_name(log_file_text)
|
50
63
|
roundtrips = parse_http_requests(log_file_text)
|
64
|
+
logger.info(f"Found #{len(roundtrips)} roundtrips")
|
65
|
+
if req.log_diff_roundtrips:
|
66
|
+
log_diff_roundtrips(roundtrips, req.differ)
|
51
67
|
api_spec_paths = parse_api_spec_paths(req.admin_api_path)
|
52
68
|
data = create_mock_data(
|
53
69
|
roundtrips,
|
54
70
|
api_spec_paths,
|
55
71
|
is_diff=req.differ,
|
56
72
|
prune_duplicates=not req.keep_duplicates,
|
73
|
+
modifiers=req.modifiers,
|
57
74
|
)
|
58
75
|
# avoid anchors
|
59
|
-
|
76
|
+
data_json = data.model_dump_json(exclude_none=True)
|
77
|
+
data_parsed = json.loads(data_json)
|
78
|
+
s = StringIO()
|
79
|
+
yaml.safe_dump(
|
80
|
+
data_parsed,
|
81
|
+
s,
|
82
|
+
default_flow_style=False,
|
83
|
+
width=100_000,
|
84
|
+
allow_unicode=True,
|
85
|
+
sort_keys=False,
|
86
|
+
)
|
87
|
+
data_yaml = s.getvalue()
|
88
|
+
test_name = test_name.replace("TestAcc", "TestMock")
|
60
89
|
output_path = req.output_dir / f"{test_name}.yaml"
|
90
|
+
logger.info(f"Variables found {data.variables}")
|
61
91
|
logger.info(f"Writing to {output_path}")
|
62
92
|
file_utils.ensure_parents_write_text(output_path, data_yaml)
|
93
|
+
return output_path
|
63
94
|
|
64
95
|
|
65
96
|
def mock_tf_log_cmd(
|
@@ -68,7 +99,7 @@ def mock_tf_log_cmd(
|
|
68
99
|
"",
|
69
100
|
"-o",
|
70
101
|
"--output-testdir",
|
71
|
-
help="the path to the output test directory, for example: internal/service/advancedclustertpf/testdata/, uses cwd/testdata by default",
|
102
|
+
help="the path to the output test directory, for example: internal/service/advancedclustertpf/testdata/, uses $(cwd)/testdata by default",
|
72
103
|
),
|
73
104
|
sdk_repo_path_str: str = option_sdk_repo_path,
|
74
105
|
sdk_branch: str = typer.Option("main", "-b", "--branch", help="the branch for downloading openapi spec"),
|
@@ -77,6 +108,9 @@ def mock_tf_log_cmd(
|
|
77
108
|
),
|
78
109
|
diff_skip_suffixes: list[str] = typer.Option(..., "-s", "--skip-suffixes", default_factory=list),
|
79
110
|
keep_duplicates: bool = typer.Option(False, "-keep", "--keep-duplicates", help="keep duplicate requests"),
|
111
|
+
log_diff_roundtrips: bool = typer.Option(
|
112
|
+
False, "-l", "--log-diff-roundtrips", help="print out the roundtrips used in diffs"
|
113
|
+
),
|
80
114
|
):
|
81
115
|
cwd = Path.cwd()
|
82
116
|
default_testdir = cwd / "testdata"
|
@@ -87,6 +121,7 @@ def mock_tf_log_cmd(
|
|
87
121
|
admin_api_path=resolved_admin_api_path,
|
88
122
|
diff_skip_suffixes=diff_skip_suffixes,
|
89
123
|
keep_duplicates=keep_duplicates,
|
124
|
+
log_diff_roundtrips=log_diff_roundtrips,
|
90
125
|
)
|
91
126
|
mock_tf_log(event_in)
|
92
127
|
|
@@ -116,3 +151,20 @@ def resolve_admin_api_path(sdk_repo_path_str: str, sdk_branch: str, admin_api_pa
|
|
116
151
|
assert resolved_admin_api_path.exists(), f"unable to resolve admin_api_path={resolved_admin_api_path}"
|
117
152
|
assert resolved_admin_api_path.is_file(), f"not a file admin_api_path={resolved_admin_api_path}"
|
118
153
|
return resolved_admin_api_path
|
154
|
+
|
155
|
+
|
156
|
+
def log_diff_roundtrips(roundtrips: list[SDKRoundtrip], differ: Callable[[SDKRoundtrip], bool] | None = None):
|
157
|
+
differ = differ or default_is_diff
|
158
|
+
diff_count = 0
|
159
|
+
step_nr = 0
|
160
|
+
for rt in roundtrips:
|
161
|
+
if not differ(rt):
|
162
|
+
continue
|
163
|
+
if rt.step_number != step_nr:
|
164
|
+
logger.info(f"{'-' * 80}\nStep {rt.step_number}")
|
165
|
+
step_nr = rt.step_number
|
166
|
+
diff_count += 1
|
167
|
+
logger.info(
|
168
|
+
f"\n{rt.request.method} {rt.request.path}\n{rt.request.text}\n{rt.response.status}-{rt.response.status_text}\n{rt.response.text}"
|
169
|
+
)
|
170
|
+
logger.info(f"Diffable requests: {diff_count}")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: atlas-init
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.2
|
4
4
|
Project-URL: Documentation, https://github.com/EspenAlbert/atlas-init#readme
|
5
5
|
Project-URL: Issues, https://github.com/EspenAlbert/atlas-init/issues
|
6
6
|
Project-URL: Source, https://github.com/EspenAlbert/atlas-init
|
@@ -1,4 +1,4 @@
|
|
1
|
-
atlas_init/__init__.py,sha256=
|
1
|
+
atlas_init/__init__.py,sha256=5-YoPkhK1DsNmcQTFT5lp8zxJ26l6WRY5tMcoGBug6o,372
|
2
2
|
atlas_init/__main__.py,sha256=dY1dWWvwxRZMmnOFla6RSfti-hMeLeKdoXP7SVYqMUc,52
|
3
3
|
atlas_init/atlas_init.yaml,sha256=GMyJVhKKRc7WzEu7fafmWgeTsDaExTLv7QvXOmE_Brg,1907
|
4
4
|
atlas_init/cli.py,sha256=IiOEC_Jry6vrSDH3_OvsU50F-_3iVIS4tV6-R7659fY,9642
|
@@ -23,13 +23,13 @@ atlas_init/cli_root/trigger.py,sha256=oEgqb_l25tyYgUaFHEuChcOCJA7k3mnRa4D-Myz-Ig
|
|
23
23
|
atlas_init/cli_tf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
24
|
atlas_init/cli_tf/app.py,sha256=0Y5c-Pc9ibOz6kXvFlL-yhH_fx1nHLgBgK9OAVqjX9s,11390
|
25
25
|
atlas_init/cli_tf/changelog.py,sha256=biWYKf1pZvXZ-jEgcZ5q9sY7nTGrL2PuI0h9mCILf_g,3181
|
26
|
-
atlas_init/cli_tf/debug_logs.py,sha256=
|
27
|
-
atlas_init/cli_tf/debug_logs_test_data.py,sha256=
|
26
|
+
atlas_init/cli_tf/debug_logs.py,sha256=r9kRMzgZGP7SB0eK7hhbxETfI28yyHFtSpvSFe9NGC4,8839
|
27
|
+
atlas_init/cli_tf/debug_logs_test_data.py,sha256=G4pnuWJ7PAQd3NXRKAtwAPC6Ne-PgpzaTZHQ9waqxZI,9565
|
28
28
|
atlas_init/cli_tf/github_logs.py,sha256=VD7qhlXNuG21eTuJ5VI7rsflp5WHSodfngkRVgQlumw,8114
|
29
29
|
atlas_init/cli_tf/go_test_run.py,sha256=ZoQSvIasmWauFxZJrWL0ObFX-P0k-D3c_ep3OnPY4zs,5842
|
30
30
|
atlas_init/cli_tf/go_test_run_format.py,sha256=OUd6QPHDeTzbwVuh6MhP-xXgjOOGP9W_sCLJ8KylBTs,1201
|
31
31
|
atlas_init/cli_tf/go_test_summary.py,sha256=agr4SITgxchjgOzRpScoTUk-iG38QDLkpnsMtTW9GTY,5382
|
32
|
-
atlas_init/cli_tf/mock_tf_log.py,sha256=
|
32
|
+
atlas_init/cli_tf/mock_tf_log.py,sha256=u_d6c-lVo3eDddpW3V5r3FJfvQvoyrC8NnOGS1bYpR8,6572
|
33
33
|
atlas_init/cli_tf/schema.py,sha256=iwvb4wD2Wba0MMu7ooTNAIi1jHbpLiXGPOT51_o_YW8,12431
|
34
34
|
atlas_init/cli_tf/schema_go_parser.py,sha256=PiRfFFVnkhltxcGFfOCgH53wwzIEynw2BXmSfaINLL8,8294
|
35
35
|
atlas_init/cli_tf/schema_inspection.py,sha256=ujLvGfg3baByND4nRD0drZoI45STxo3VfYvim-PfVOc,1764
|
@@ -86,7 +86,7 @@ atlas_init/tf/modules/vpc_peering/vpc_peering.tf,sha256=hJ3KJdGbLpOQednUpVuiJ0Cq
|
|
86
86
|
atlas_init/tf/modules/vpc_privatelink/atlas-privatelink.tf,sha256=FloaaX1MNDvoMZxBnEopeLKyfIlq6kaX2dmx8WWlXNU,1298
|
87
87
|
atlas_init/tf/modules/vpc_privatelink/variables.tf,sha256=gktHCDYD4rz6CEpLg5aiXcFbugw4L5S2Fqc52QYdJyc,255
|
88
88
|
atlas_init/tf/modules/vpc_privatelink/versions.tf,sha256=G0u5V_Hvvrkux_tqfOY05pA-GzSp_qILpfx1dZaTGDc,237
|
89
|
-
atlas_init-0.3.
|
90
|
-
atlas_init-0.3.
|
91
|
-
atlas_init-0.3.
|
92
|
-
atlas_init-0.3.
|
89
|
+
atlas_init-0.3.2.dist-info/METADATA,sha256=foETVpu_FKi1rkGOJB158pmAftoNYFiG9VNr1kPBPvA,5650
|
90
|
+
atlas_init-0.3.2.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
91
|
+
atlas_init-0.3.2.dist-info/entry_points.txt,sha256=oSNFIEAS9nUZyyZ8Fc-0F0U5j-NErygy01LpJVSHapQ,57
|
92
|
+
atlas_init-0.3.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|