|
| 1 | +""" |
| 2 | +Health Report Integration test bootstrapper with Python script |
| 3 | + - A script to resolve Logstash version if not provided |
| 4 | + - Download LS docker image and spin up |
| 5 | + - When tests finished, teardown the Logstash |
| 6 | +""" |
| 7 | +import os |
| 8 | +import subprocess |
| 9 | +import util |
| 10 | +import yaml |
| 11 | + |
| 12 | + |
| 13 | +class Bootstrap: |
| 14 | + ELASTIC_STACK_VERSIONS_URL = "https://artifacts-api.elastic.co/v1/versions" |
| 15 | + |
| 16 | + def __init__(self) -> None: |
| 17 | + f""" |
| 18 | + A constructor of the {Bootstrap}. |
| 19 | + Returns: |
| 20 | + Resolves Logstash branch considering provided LS_VERSION |
| 21 | + Checks out git branch |
| 22 | + """ |
| 23 | + logstash_version = os.environ.get("LS_VERSION") |
| 24 | + if logstash_version is None: |
| 25 | + # version is not specified, use the main branch, no need to git checkout |
| 26 | + print(f"LS_VERSION is not specified, using main branch.") |
| 27 | + else: |
| 28 | + # LS_VERSION accepts major latest as a major.x or specific version as X.Y |
| 29 | + if logstash_version.find(".x") == -1: |
| 30 | + print(f"Using specified branch: {logstash_version}") |
| 31 | + util.git_check_out_branch(logstash_version) |
| 32 | + else: |
| 33 | + major_version = logstash_version.split(".")[0] |
| 34 | + if major_version and major_version.isnumeric(): |
| 35 | + resolved_version = self.__resolve_latest_stack_version_for(major_version) |
| 36 | + minor_version = resolved_version.split(".")[1] |
| 37 | + branch = major_version + "." + minor_version |
| 38 | + print(f"Using resolved branch: {branch}") |
| 39 | + util.git_check_out_branch(branch) |
| 40 | + else: |
| 41 | + raise ValueError(f"Invalid value set to LS_VERSION. Please set it properly (ex: 8.x or 9.0) and " |
| 42 | + f"rerun again") |
| 43 | + |
| 44 | + def __resolve_latest_stack_version_for(self, major_version: str) -> None: |
| 45 | + resolved_version = "" |
| 46 | + response = util.call_url_with_retry(self.ELASTIC_STACK_VERSIONS_URL) |
| 47 | + release_versions = response.json()["versions"] |
| 48 | + for release_version in reversed(release_versions): |
| 49 | + if release_version.find("SNAPSHOT") > 0: |
| 50 | + continue |
| 51 | + if release_version.split(".")[0] == major_version: |
| 52 | + print(f"Resolved latest version for {major_version} is {release_version}.") |
| 53 | + resolved_version = release_version |
| 54 | + break |
| 55 | + |
| 56 | + if resolved_version == "": |
| 57 | + raise ValueError(f"Cannot resolve latest version for {major_version} major") |
| 58 | + return resolved_version |
| 59 | + |
| 60 | + def install_plugin(self, plugin_path: str) -> None: |
| 61 | + util.run_or_raise_error( |
| 62 | + ["bin/logstash-plugin", "install", plugin_path], |
| 63 | + f"Failed to install {plugin_path}") |
| 64 | + |
| 65 | + def build_logstash(self): |
| 66 | + print(f"Building Logstash.") |
| 67 | + util.run_or_raise_error( |
| 68 | + ["./gradlew", "clean", "bootstrap", "assemble", "installDefaultGems"], |
| 69 | + "Failed to build Logstash") |
| 70 | + print(f"Logstash has successfully built.") |
| 71 | + |
| 72 | + def apply_config(self, config: dict) -> None: |
| 73 | + with open(os.getcwd() + "/config/pipelines.yml", 'w') as pipelines_file: |
| 74 | + yaml.dump(config, pipelines_file) |
| 75 | + |
| 76 | + def run_logstash(self) -> subprocess.Popen: |
| 77 | + process = subprocess.Popen(["bin/logstash"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) |
| 78 | + if process.poll() is not None: |
| 79 | + print(f"Logstash failed to run, check the the config and logs, then rerun.") |
| 80 | + return None |
| 81 | + |
| 82 | + # Read stdout and stderr in real-time |
| 83 | + logs = [] |
| 84 | + for stdout_line in iter(process.stdout.readline, ""): |
| 85 | + # print("STDOUT:", stdout_line.strip()) |
| 86 | + logs.append(stdout_line.strip()) |
| 87 | + if "Starting pipeline" in stdout_line: |
| 88 | + break |
| 89 | + if "Logstash shut down" in stdout_line: |
| 90 | + print(f"Logstash couldn't spin up.") |
| 91 | + print(logs) |
| 92 | + return None |
| 93 | + |
| 94 | + print(f"Logstash is running with PID: {process.pid}.") |
| 95 | + return process |
| 96 | + |
| 97 | + def stop_logstash(self, process: subprocess.Popen) -> None: |
| 98 | + process.terminate() |
| 99 | + print(f"Stopping Logstash...") |
0 commit comments