diff --git a/miraheze/puppet/upgrade-cp-service.py b/miraheze/puppet/upgrade-cp-service.py index 531be0b..f371660 100644 --- a/miraheze/puppet/upgrade-cp-service.py +++ b/miraheze/puppet/upgrade-cp-service.py @@ -46,6 +46,13 @@ class EnvironmentList(TypedDict): class ServersAction(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): # noqa: U100 + """ + Parse and validate server choices from a comma-separated input string. + + Splits the input into individual server names and verifies each against the current + environment's valid servers. If the keyword "all" is present, it replaces the list with + all available servers. Triggers a parser error if any invalid server names are found. + """ input_servers = values.split(',') valid_servers = get_environment_info()['servers'] if 'all' in input_servers: @@ -56,7 +63,20 @@ def __call__(self, parser, namespace, values, option_string=None): # noqa: U100 setattr(namespace, self.dest, input_servers) def run_command(command): - """Runs a shell command and returns the output.""" + """ + Executes a shell command and returns its output. + + This function runs the given command in a subshell using the subprocess module. + It captures the command's standard output and returns it after stripping any + extraneous whitespace. If the command fails, it prints an error message and + returns None. + + Args: + command (str): The shell command to execute. + + Returns: + str or None: The command's output if successful; otherwise, None. + """ try: result = subprocess.run(command, shell=True, check=True, capture_output=True, text=True) return result.stdout.strip() @@ -65,7 +85,21 @@ def run_command(command): return None def wait_for_ping(server, timeout=300, interval=5): - """Waits for the server to respond to ping.""" + """ + Waits for a server to become reachable via ping. + + Repeatedly pings the specified server at regular intervals until it responds or the timeout is reached. + Prints status messages indicating whether the server has come back online, and returns a boolean + value signifying the server's availability. + + Args: + server: The address or hostname of the server to ping. + timeout: The maximum time in seconds to wait for a response (default is 300). + interval: The interval in seconds between consecutive ping attempts (default is 5). + + Returns: + True if the server responds within the timeout period, otherwise False. + """ print(f"Waiting for {server} to come back online...") start_time = time.time() while time.time() - start_time < timeout: @@ -78,6 +112,25 @@ def wait_for_ping(server, timeout=300, interval=5): return False def check_up(Debug: str, domain: str = 'meta.miraheze.org', verify: bool = True) -> bool: + """ + Checks whether the target service is operational by querying its MediaWiki API. + + This function sends a GET request over HTTPS to the API endpoint at the given domain. + If a debug identifier is provided, it attaches custom headers and verifies that the + response header includes the expected debug context. The service is considered up if the + response has a 200 status code, contains the 'miraheze' marker in its body, and, when + debugging is active, the debug identifier is present in the 'X-Served-By' header. + SSL verification is controlled by the verify flag (with warnings suppressed when disabled). + Diagnostic messages are printed if the service does not meet these checks. + + Parameters: + Debug: A debug identifier used to insert and validate custom headers. + domain: The service domain to query (default "meta.miraheze.org"). + verify: Flag to enforce SSL certificate verification (default True). + + Returns: + True if the service is healthy; otherwise, False. + """ if verify is False: os.environ['PYTHONWARNINGS'] = 'ignore:Unverified HTTPS request' @@ -105,7 +158,18 @@ def check_up(Debug: str, domain: str = 'meta.miraheze.org', verify: bool = True) return up def process_server(server): - """Performs the sequence of commands for a given server.""" + """ + Processes the upgrade workflow for the specified server. + + This function orchestrates the server upgrade steps by marking the backend as sick, + upgrading packages, rebooting the server, and then verifying that the server is back online. + If the server responds to a ping, it conducts a health check and, if successful, restores + the backend health to auto. If the health check fails or the server does not respond to ping, + the function pauses until the user confirms to continue. + + Parameters: + server: The hostname or identifier of the server to process. + """ print(f"Processing {server}...") # Mark backend as sick @@ -138,4 +202,4 @@ def process_server(server): parser.add_argument('--servers', dest='servers', action=ServersAction, required=True, help='server(s) to deploy to') args = parser.parse_args() for server in args.servers: - process_server(server) + process_server(args.servers)