Skip to content

Commit c36470f

Browse files
authored
aws script to update aws hard-coded variables (#89)
1 parent 69f68e0 commit c36470f

File tree

2 files changed

+184
-0
lines changed

2 files changed

+184
-0
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#!/usr/bin/env python3
2+
"""Script to update boto* library constraints aws hard-coded variable."""
3+
4+
import logging
5+
import os
6+
import re
7+
8+
from functools import partial
9+
from pathlib import PosixPath
10+
11+
12+
FORMAT = "[%(asctime)s] - %(message)s"
13+
logging.basicConfig(format=FORMAT)
14+
logger = logging.getLogger("update_aws_user_agent")
15+
logger.setLevel(logging.DEBUG)
16+
17+
MIN_BOTOCORE_RE = re.compile(r"MINIMUM_BOTOCORE_VERSION( *)=( *)[\"|'][0-9\.]+[\"|']")
18+
MIN_BOTO3_RE = re.compile(r"MINIMUM_BOTO3_VERSION( *)=( *)[\"|'][0-9\.]+[\"|']")
19+
20+
21+
def replace_vars(values: dict[str, str], line: str) -> str:
22+
"""Replace a variable from a string.
23+
24+
:param values: A dictionary of values to search into strin.
25+
:param line: The string to replace values in.
26+
:returns: The updated string.
27+
"""
28+
res = None
29+
for var, value in values.items():
30+
match = re.match(rf"^{var}([ =\"']*)[0-9\.]+(.*)", line)
31+
if match:
32+
res = var + match.group(1) + value + match.group(2)
33+
break
34+
return line if res is None else res
35+
36+
37+
def update_single_file(path: str, values: dict[str, str]) -> None:
38+
"""Update requirement file with boto3 and botocore constraints.
39+
40+
:param path: The path to the file to update.
41+
:param values: dictionary of boto3 and botocore constraints
42+
"""
43+
with open(path, encoding="utf-8") as file_read:
44+
content = file_read.read().split("\n")
45+
new_content = list(map(partial(replace_vars, values), content))
46+
if new_content != content:
47+
with open(path, "w", encoding="utf-8") as file_write:
48+
file_write.write("\n".join(new_content))
49+
logger.info("%s => updated", path)
50+
51+
52+
def update_tests_constraints(boto3_version: str, botocore_version: str) -> None:
53+
"""Update boto3 and botocore constraints from requirement file.
54+
55+
:param boto3_version: The boto3 version to define.
56+
:param botocore_version: The boto core version to define.
57+
"""
58+
boto_values = {"boto3": boto3_version, "botocore": botocore_version}
59+
for file in ("tests/unit/constraints.txt", "tests/integration/constraints.txt"):
60+
update_single_file(file, boto_values)
61+
62+
min_boto_values = {
63+
"MINIMUM_BOTO3_VERSION": boto3_version,
64+
"MINIMUM_BOTOCORE_VERSION": botocore_version,
65+
}
66+
for root, _, files in os.walk("plugins"):
67+
for name in files:
68+
if not name.endswith(".py"):
69+
continue
70+
update_single_file(os.path.join(root, name), min_boto_values)
71+
72+
73+
def read_boto_version() -> tuple[str, str]:
74+
"""Read boto version constraints from requirement file.
75+
76+
:returns: Tuple of boto3 and botocore version constraints
77+
"""
78+
botocore_regex = re.compile(r"^botocore[>=<]+([0-9\.]+)", re.MULTILINE | re.IGNORECASE)
79+
boto3_regex = re.compile(r"^boto3[>=<]+([0-9\.]+)", re.MULTILINE | re.IGNORECASE)
80+
81+
with PosixPath("requirements.txt").open(encoding="utf-8") as file_desc:
82+
content = file_desc.read()
83+
m_boto3 = boto3_regex.search(content)
84+
m_botocore = botocore_regex.search(content)
85+
return m_boto3.group(1) if m_boto3 else "", m_botocore.group(1) if m_botocore else ""
86+
87+
88+
def main() -> None:
89+
"""Read boto constraints and update variables accordingly."""
90+
boto3_version, botocore_version = read_boto_version()
91+
logger.info("boto3='%s' - botocore='%s'", boto3_version, botocore_version)
92+
update_tests_constraints(boto3_version, botocore_version)
93+
94+
95+
if __name__ == "__main__":
96+
main()

scripts/update_aws_user_agent.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#!/usr/bin/env python3
2+
"""Script to update aws hard-coded user agent variable with value from galaxy.yml."""
3+
4+
import logging
5+
import re
6+
7+
from pathlib import PosixPath
8+
9+
import yaml
10+
11+
12+
FORMAT = "[%(asctime)s] - %(message)s"
13+
logging.basicConfig(format=FORMAT)
14+
logger = logging.getLogger("update_aws_user_agent")
15+
logger.setLevel(logging.DEBUG)
16+
17+
18+
def update_user_agent(src: PosixPath, var_name: str, galaxy_version: str) -> bool:
19+
"""Update aws user agent variable from file passed in input.
20+
21+
:param src: The path to the file to search variable in.
22+
:param var_name: The name of the variable to update
23+
:param galaxy_version: The collection version stored into galaxy.yml
24+
:returns: Whether the variable has been updated
25+
"""
26+
variable_regex = rf"^{var_name} = [\"|'](.*)[\"|']"
27+
new_content = []
28+
updated = False
29+
logger.info("********** Parsing file => %s *************", src.stem)
30+
with src.open() as file_handler:
31+
for line in file_handler.read().split("\n"):
32+
match = re.match(variable_regex, line)
33+
if match and match.group(1) != galaxy_version:
34+
logger.info("Match variable [%s] with value [%s]", var_name, match.group(1))
35+
updated = True
36+
new_content.append(f'{var_name} = "{galaxy_version}"')
37+
else:
38+
new_content.append(line)
39+
40+
if updated:
41+
src.write_text("\n".join(new_content))
42+
return updated
43+
44+
45+
def update_collection_user_agent(var_name: str, galaxy_version: str) -> bool:
46+
"""Update aws variable name with value provided as input.
47+
48+
:param var_name: The name of the variable to update
49+
:param galaxy_version: The collection version stored into galaxy.yml
50+
:returns: Whether the variable has been updated somewhere
51+
"""
52+
53+
def _get_files_from_directory(path: PosixPath) -> list[PosixPath]:
54+
if not path.is_dir():
55+
return [path]
56+
result = []
57+
for child in path.iterdir():
58+
result.extend(_get_files_from_directory(child))
59+
return result
60+
61+
return any(
62+
update_user_agent(src, var_name, galaxy_version)
63+
for src in _get_files_from_directory(PosixPath("plugins"))
64+
if str(src).endswith(".py")
65+
)
66+
67+
68+
def main() -> None:
69+
"""Read collection info and update aws user agent if needed."""
70+
# Read collection information from galaxy.yml
71+
collection_info = {}
72+
with PosixPath("galaxy.yml").open(encoding="utf-8") as file_desc:
73+
collection_info = yaml.safe_load(file_desc)
74+
logger.info("collection information from galaxy.yml: %s", collection_info)
75+
variable_name = (
76+
collection_info["namespace"].upper()
77+
+ "_"
78+
+ collection_info["name"].upper()
79+
+ "_COLLECTION_VERSION"
80+
)
81+
logger.info("Expecting collection user-agent variable => '%s'", variable_name)
82+
83+
galaxy_version = collection_info["version"]
84+
update_collection_user_agent(variable_name, galaxy_version)
85+
86+
87+
if __name__ == "__main__":
88+
main()

0 commit comments

Comments
 (0)