|
6 | 6 | import base64
|
7 | 7 | import subprocess
|
8 | 8 | import shlex
|
| 9 | +import shutil |
| 10 | +from pathlib import Path |
| 11 | +from zipfile import ZipFile |
| 12 | +from typing import List |
9 | 13 |
|
| 14 | +SLIDES: str = "\n" + ("=" * 40) + "\n" |
10 | 15 |
|
11 |
| -def extract_war_files(webapps_dir, webapps_ref, path_prefix): |
12 |
| - """ |
13 |
| - Prepare webapps on first-time startup: |
14 |
| - - Extract WAR files from webapps-ref to webapps. |
15 |
| - - Modify log4j to send logs to stdout. |
16 |
| - - Modify context path (pathPrefix) if given. |
17 |
| -
|
18 |
| - :param webapps_dir: Path to the webapps directory. |
19 |
| - :param webapps_ref: Path to the webapps reference directory. |
20 |
| - :param path_prefix: Prefix for the context path. |
| 16 | +def extract(source: Path, destination: Path, prefix:str = "/", kind: str = "war"): |
| 17 | + """Extract a file to a destination directory. |
| 18 | +
|
| 19 | + Args: |
| 20 | + source (Path): Source directory to extract from |
| 21 | + destination (Path): Destination directory to extract to |
| 22 | + prefix (str, optional): Prefix extracted filepaths. Default is "/". |
| 23 | + kind (str, optional): File extension to extract. Default is "war". |
21 | 24 | """
|
22 |
| - if not os.listdir(webapps_dir): |
23 |
| - for war in os.listdir(webapps_ref): |
24 |
| - if war.endswith(".war"): |
25 |
| - fn = os.path.splitext(war)[0] |
26 |
| - prefix = path_prefix.replace("/", "#").strip("#") |
27 |
| - war_dir = os.path.join(webapps_dir, f"{prefix}#{fn}" if prefix else fn) |
28 |
| - os.makedirs(war_dir, exist_ok=True) |
29 |
| - subprocess.call(["unzip", "-oqd", war_dir, os.path.join(webapps_ref, war)]) |
30 |
| - subprocess.call(["sed", "-E", "-i.bak", "s/##out--//", os.path.join(war_dir, "WEB-INF/classes/log4j2.properties")]) |
| 25 | + print(f"{SLIDES} Extracting {kind.upper()} files {SLIDES}") |
| 26 | + extractions: dict[str, Path] = {} |
| 27 | + for item in source.iterdir(): |
| 28 | + # Only extract specified file extensions |
| 29 | + if item.is_file() and item.suffix == f".{kind}": |
| 30 | + filename = item.stem |
| 31 | + |
| 32 | + # Configure prefix for extracted files |
| 33 | + prefix = prefix.replace("/", "#").strip("#") |
| 34 | + if prefix: |
| 35 | + filename = f"{prefix}#{filename}" |
| 36 | + |
| 37 | + # Create landing directory for extracted files |
| 38 | + landing = destination / filename |
| 39 | + landing.mkdir(parents=True, exist_ok=True) |
| 40 | + |
| 41 | + # Extract archive to landing directory |
| 42 | + print(f"Extracting {item} to {landing}") |
| 43 | + with ZipFile(item, "r") as archive: |
| 44 | + archive.extractall(landing) |
| 45 | + print(f"Extracted {item} to {landing}") |
| 46 | + extractions[filename] = landing |
| 47 | + |
| 48 | + # Modify log4j to send logs to stdout |
| 49 | + log4j = destination / "WEB-INF/classes/log4j2.properties" |
| 50 | + if log4j.exists(): |
| 51 | + # Create backup as log4j.properties.bak |
| 52 | + print(f"Modifying {log4j}") |
| 53 | + shutil.copy(log4j, log4j.with_suffix(".bak")) |
| 54 | + with open(log4j, 'r+') as file: |
| 55 | + content = file.read() |
| 56 | + content = content.replace("##out--", "") |
| 57 | + file.seek(0) |
| 58 | + file.write(content) |
| 59 | + file.truncate() |
| 60 | + |
| 61 | + # Copy secondary files for extracted archives to landing directory |
| 62 | + for filename, landing in extractions.items(): |
| 63 | + origin = source / f"{filename}" |
| 64 | + for item in origin.iterdir(): |
| 65 | + if item.is_dir(): |
| 66 | + print(f"Copying directory {item} to {landing}") |
| 67 | + shutil.copytree(item, landing / item.name, dirs_exist_ok=True) |
| 68 | + else: |
| 69 | + print(f"Copying file {item} to {landing}") |
| 70 | + shutil.copy2(item, landing / item.name) |
| 71 | + print(f"{SLIDES} Extractions complete {SLIDES}") |
31 | 72 |
|
32 | 73 |
|
33 | 74 | def add_multi_props_env_var():
|
@@ -120,32 +161,35 @@ def log_env_info(path_prefix, visualize_fits_search_path):
|
120 | 161 | """)
|
121 | 162 |
|
122 | 163 |
|
123 |
| -def show_help(name): |
124 |
| - """Show help message and exit.""" |
| 164 | +def show_help(name:str, webapps_ref: Path): |
| 165 | + """Show help message and examples. |
| 166 | +
|
| 167 | + Args: |
| 168 | + name (str): Application name |
| 169 | + webapps_ref (Path): Reference webapps directory |
| 170 | + """ |
125 | 171 | with open("./start-examples.txt") as f:
|
126 | 172 | print(f.read().replace("ipac/firefly", name))
|
127 | 173 |
|
128 |
| - war_files = [f for f in os.listdir(webapps_ref) if f.endswith(".war")] |
129 |
| - if war_files and war_files[0] == "firefly.war": |
130 |
| - with open("./customize-firefly.txt") as f: |
131 |
| - print(f.read()) |
| 174 | + for item in webapps_ref.iterdir(): |
| 175 | + if item.is_file() and item.stem == "firefly" and item.suffix == ".war" : |
| 176 | + with open("./customize-firefly.txt") as f: |
| 177 | + print(f.read()) |
132 | 178 | sys.exit(0)
|
133 | 179 |
|
134 |
| - |
135 |
| -def dry_run(cmd, webapps_dir): |
| 180 | +def dry_run(cmd: List[str], webapps: Path): |
136 | 181 | """Display a dry run of the command and environment setup."""
|
137 |
| - print("\n\n----------------------") |
138 |
| - print(f"Command: {' '.join(cmd)}") |
| 182 | + |
| 183 | + print(f"\n{SLIDES} DRY RUN {SLIDES}") |
| 184 | + print(f"COMMAND : {' '.join(cmd)}") |
139 | 185 | print(f"CATALINA_OPTS: {os.getenv('CATALINA_OPTS')}\n")
|
140 |
| - |
141 |
| - print(f"Contents of '{webapps_dir}':") |
142 |
| - for item in os.listdir(webapps_dir): |
143 |
| - item_path = os.path.join(webapps_dir, item) |
144 |
| - if os.path.isdir(item_path): |
145 |
| - print(f" [DIR] {item}") |
| 186 | + print(f"WEBAPPS : {webapps}':") |
| 187 | + for item in webapps.iterdir(): |
| 188 | + if item.is_dir(): |
| 189 | + print(f" [DIR] {item.name}") |
146 | 190 | else:
|
147 |
| - print(f" [FILE] {item}") |
148 |
| - print() |
| 191 | + print(f" [FILE] {item.name}") |
| 192 | + print(f"{SLIDES} DRY RUN COMPLETE {SLIDES}") |
149 | 193 | sys.exit(0)
|
150 | 194 |
|
151 | 195 |
|
@@ -208,18 +252,18 @@ def main():
|
208 | 252 | # Setup examples
|
209 | 253 | subprocess.call("./setupFireflyExample.sh", shell=True)
|
210 | 254 |
|
211 |
| - # Prepare webapps on first-time startup |
212 |
| - webapps_dir = os.path.join(catalina_home, "webapps") |
213 |
| - webapps_ref = os.path.join(catalina_home, "webapps-ref") |
214 |
| - extract_war_files(webapps_dir, webapps_ref, path_prefix) |
| 255 | + catalina: Path = Path(catalina_home) |
| 256 | + webapps_ref: Path = catalina / "webapps-ref" |
| 257 | + webapps: Path = catalina / "webapps" |
| 258 | + extract(source = webapps_ref, destination=webapps, prefix = path_prefix, kind="war") |
215 | 259 |
|
216 | 260 | # check for no-ops flags
|
217 | 261 | if len(sys.argv) > 1:
|
218 | 262 | arg = sys.argv[1]
|
219 | 263 | if arg in ["--help", "-help", "-h"]:
|
220 |
| - show_help(name) |
| 264 | + show_help(name, webapps_ref) |
221 | 265 | elif arg == "--dry-run":
|
222 |
| - dry_run(cmd, webapps_dir) |
| 266 | + dry_run(cmd, webapps) |
223 | 267 |
|
224 | 268 | # Start background cleanup
|
225 | 269 | subprocess.Popen([f"{catalina_home}/cleanup.sh", "/firefly/workarea", "/firefly/shared-workarea"])
|
|
0 commit comments