Skip to content

Commit 40c6d48

Browse files
committed
Adjust repo files
1 parent d7db5dc commit 40c6d48

File tree

4 files changed

+277
-52
lines changed

4 files changed

+277
-52
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,15 @@
44
## Unreleased
55

66

7-
## Release 0.143
7+
## Release 0.144
88

99
### Changed
10+
- Split out PHP extensions int separate directories
11+
12+
13+
## Release 0.143
14+
15+
### Added
1016
- Added `phalcon` 5.x to PHP 8.0 and PHP 8.1
1117

1218

bin/modules-generate.py

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
"""Generate Ansible group_vars from module definition."""
4+
import os
5+
import sys
6+
from collections import OrderedDict
7+
from typing import Dict, List, Optional, Any
8+
import yaml
9+
10+
11+
# --------------------------------------------------------------------------------------------------
12+
# GLOBALS
13+
# --------------------------------------------------------------------------------------------------
14+
15+
SCRIPT_PATH = str(os.path.dirname(os.path.realpath(__file__)))
16+
REPOSITORY_PATH = str(os.path.dirname(SCRIPT_PATH))
17+
PHP_MODULE_PATH = str(os.path.join(REPOSITORY_PATH, "php_modules"))
18+
GROUP_VARS_PATH = str(os.path.join(REPOSITORY_PATH, ".ansible", "group_vars", "all"))
19+
20+
21+
# --------------------------------------------------------------------------------------------------
22+
# HELPER FUNCTIONS
23+
# --------------------------------------------------------------------------------------------------
24+
25+
26+
def get_el_by_name(items: List[Dict[str, Any]], name: str) -> Dict[str, Any]:
27+
"""Returns an element from a dict list by its 'name' key with given value."""
28+
for item in items:
29+
if item["name"] == name:
30+
return item
31+
print("error, key name not found by value", name, "in list: ", items)
32+
sys.exit(1)
33+
34+
35+
def load_yaml(path: str) -> Dict[str, Any]:
36+
"""Load yaml file and return its dict()."""
37+
with open(path, "r", encoding="utf8") as fp:
38+
data = yaml.safe_load(fp)
39+
return data
40+
41+
42+
def load_yaml_raw(path: str, indent: int = 0) -> str:
43+
"""Load and returns yaml file as str."""
44+
lines = []
45+
with open(path, "r", encoding="utf8") as fp:
46+
for line in fp:
47+
# Remove: empty lines and ---
48+
if line in ("---\n", "---\r\n", "\n", "\r\n"):
49+
continue
50+
# Remove: comments
51+
if line.startswith("#"):
52+
continue
53+
lines.append(" " * indent + line)
54+
return "".join(lines)
55+
56+
57+
# --------------------------------------------------------------------------------------------------
58+
# MODULE FUNCTIONS
59+
# --------------------------------------------------------------------------------------------------
60+
61+
62+
def get_module_options(module_dirname: str) -> Dict[str, Any]:
63+
"""Returns yaml dict options of a PHP module given by its absolute file path."""
64+
return load_yaml(os.path.join(PHP_MODULE_PATH, module_dirname, "options.yml"))
65+
66+
67+
def get_module_build(module_dirname: str) -> Dict[str, Any]:
68+
"""Returns yaml dict build configuration of a PHP module given by its absolute file path."""
69+
return load_yaml(os.path.join(PHP_MODULE_PATH, module_dirname, "build.yml"))
70+
71+
72+
def get_module_test(module_dirname: str) -> Dict[str, Any]:
73+
"""Returns yaml dict test configuration of a PHP module given by its absolute file path."""
74+
return load_yaml(os.path.join(PHP_MODULE_PATH, module_dirname, "test.yml"))
75+
76+
77+
def get_modules(mod_name: Optional[str] = None) -> List[Dict[str, Any]]:
78+
"""Returns a list of PHP module directory names.
79+
80+
Args:
81+
mod_name: If specified, only get this module (and its dependencies).
82+
"""
83+
modules = []
84+
with os.scandir(PHP_MODULE_PATH) as it:
85+
for item in it:
86+
if not item.name.startswith(".") and item.is_dir():
87+
data = get_module_options(item.name)
88+
modules.append(
89+
{"dir": item.name, "name": data["name"], "deps": data["depends_build"]}
90+
)
91+
# Convert list of deps into dict(dir, name, deps)
92+
items = []
93+
for module in modules:
94+
if module["deps"]:
95+
deps = []
96+
for dep in module["deps"]:
97+
deps.append(get_el_by_name(modules, dep))
98+
module["deps"] = deps
99+
items.append(module)
100+
else:
101+
items.append(module)
102+
# Check if we only want to read a single module
103+
if mod_name:
104+
return [get_el_by_name(items, mod_name)]
105+
return sorted(items, key=lambda item: item["dir"])
106+
107+
108+
def get_module_dependency_tree(modules: List[Dict[str, Any]]) -> OrderedDict[str, Any]:
109+
"""Returns dictionary of module dependency tree."""
110+
module_tree = OrderedDict() # type: OrderedDict[str, Any]
111+
112+
for module in modules:
113+
mod_name = module["name"]
114+
mod_deps = module["deps"]
115+
116+
module_tree[mod_name] = {}
117+
118+
# Do we have module requirements?
119+
if len(mod_deps) > 0:
120+
module_tree[mod_name] = get_module_dependency_tree(mod_deps)
121+
return module_tree
122+
123+
124+
def resolve_module_dependency_tree(tree: OrderedDict[str, Any]) -> List[str]:
125+
"""Returns sorted list of resolved dependencies."""
126+
resolved = []
127+
for key, _ in tree.items():
128+
# Has dependenies
129+
if tree[key]:
130+
childs = resolve_module_dependency_tree(tree[key])
131+
for child in childs:
132+
if child not in resolved:
133+
resolved.append(child)
134+
# Add current node, if not already available
135+
if key not in resolved:
136+
resolved.append(key)
137+
return resolved
138+
139+
140+
# --------------------------------------------------------------------------------------------------
141+
# PRINT FUNCTIONS
142+
# --------------------------------------------------------------------------------------------------
143+
144+
145+
def print_modules(modules: List[Dict[str, Any]]) -> None:
146+
"""Print directory modules."""
147+
for module in modules:
148+
print(module["dir"] + "/")
149+
print(" name:", module["name"])
150+
print(" deps:", end=" ")
151+
for dep in module["deps"]:
152+
print(dep["name"], end=", ")
153+
print()
154+
155+
156+
def print_dependency_tree(tree: Dict[str, Any], lvl: int = 0) -> None:
157+
"""Print dependency tree of modules."""
158+
for key, value in tree.items():
159+
print(" " * lvl, "-", key)
160+
if value:
161+
print_dependency_tree(tree[key], lvl + 2)
162+
163+
164+
# --------------------------------------------------------------------------------------------------
165+
# WRITE ANSIBLE GROUP_VARS FUNCTIONS
166+
# --------------------------------------------------------------------------------------------------
167+
168+
169+
def write_group_vars(modules: List[str]) -> None:
170+
"""Write mods.yml group_vars for ansible."""
171+
group_vars = os.path.join(GROUP_VARS_PATH, "mods.yml")
172+
173+
with open(group_vars, "w", encoding="utf8") as fp:
174+
fp.write("---\n\n")
175+
fp.write("# DO NOT ALTER THIS FILE - IT IS AUTOGENERATED.\n\n")
176+
177+
# Enabled modules
178+
fp.write("# The following specifies the order in which modules are being built.\n")
179+
fp.write("extensions_enabled:\n")
180+
for module in modules:
181+
fp.write(" - " + module + "\n")
182+
fp.write("\n\n")
183+
184+
# Build defines modules
185+
fp.write("# The following specifies how modules are being built.\n")
186+
fp.write("extensions_available:\n")
187+
for module in modules:
188+
opts = get_module_options(module)
189+
fp.write(" " + module + ":\n")
190+
fp.write(" disabled: [" + ", ".join(str(x) for x in opts["exclude"]) + "]\n")
191+
fp.write(load_yaml_raw(os.path.join(PHP_MODULE_PATH, module, "build.yml"), 4))
192+
193+
194+
# --------------------------------------------------------------------------------------------------
195+
# MAIN FUNCTION
196+
# --------------------------------------------------------------------------------------------------
197+
def print_help() -> None:
198+
"""Show help screen."""
199+
print("Usage:", os.path.basename(__file__), "[php-module]")
200+
print(" ", os.path.basename(__file__), "-h, --help")
201+
print()
202+
print("This script will generate the Ansible group_vars file: .ansible/group_vars/all/mods.yml")
203+
print("based on all the modules found in php_modules/ directory.")
204+
print()
205+
print("Optional arguments:")
206+
print(" [php-module] When specifying a name of a php-module, the group_vars file will")
207+
print(" only be generated for this single module (and its dependencies).")
208+
print(" This is useful if you want to test new modules and not build all")
209+
print(" previous modules in the Dockerfile.")
210+
print()
211+
print(" Note: You still need to generate the Dockerfiles via Ansible for")
212+
print(" the changes to take effect, before building the image.")
213+
214+
215+
def main(argv: List[str]) -> None:
216+
"""Main entrypoint."""
217+
if not (len(argv) == 0 or len(argv) == 1):
218+
print_help()
219+
sys.exit(1)
220+
if len(argv) == 1:
221+
if argv[0] == "--help" or argv[0] == "-h":
222+
print_help()
223+
sys.exit(0)
224+
225+
single_module = None
226+
if len(argv) == 1:
227+
single_module = argv[0]
228+
229+
# Get modules in order of dependencies
230+
modules = get_modules(single_module)
231+
module_tree = get_module_dependency_tree(modules)
232+
names = resolve_module_dependency_tree(module_tree)
233+
234+
print("#", "-" * 78)
235+
print("# Paths")
236+
print("#", "-" * 78)
237+
print("Repository: ", REPOSITORY_PATH)
238+
print("PHP Module: ", PHP_MODULE_PATH)
239+
print("Group Vars: ", GROUP_VARS_PATH)
240+
print()
241+
242+
print("#", "-" * 78)
243+
print("# Module directories")
244+
print("#", "-" * 78)
245+
print_modules(modules)
246+
print()
247+
248+
print("#", "-" * 78)
249+
print("# Build Dependency Tree")
250+
print("#", "-" * 78)
251+
print_dependency_tree(module_tree)
252+
print()
253+
254+
print("#", "-" * 78)
255+
print("# Build order")
256+
print("#", "-" * 78)
257+
print("\n".join(names))
258+
259+
# Create group_vars file mods.yml
260+
write_group_vars(names)
261+
262+
263+
if __name__ == "__main__":
264+
main(sys.argv[1:])

bin/modules-validate.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
"""Validate defined modules."""
4+
print("Not yet implemented *///*")
5+
print()
6+
print("Run modules-generate.py instead, as it also kind of validates.")

build/README.md

Lines changed: 0 additions & 51 deletions
This file was deleted.

0 commit comments

Comments
 (0)