1*6777b538SAndroid Build Coastguard Worker#!/usr/bin/env vpython3 2*6777b538SAndroid Build Coastguard Worker# Copyright 2022 The Chromium Authors 3*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 4*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file. 5*6777b538SAndroid Build Coastguard Worker"""Implements commands for serving a TUF repository.""" 6*6777b538SAndroid Build Coastguard Worker 7*6777b538SAndroid Build Coastguard Workerimport argparse 8*6777b538SAndroid Build Coastguard Workerimport contextlib 9*6777b538SAndroid Build Coastguard Workerimport sys 10*6777b538SAndroid Build Coastguard Worker 11*6777b538SAndroid Build Coastguard Workerfrom typing import Iterator, Optional 12*6777b538SAndroid Build Coastguard Worker 13*6777b538SAndroid Build Coastguard Workerfrom common import REPO_ALIAS, catch_sigterm, register_device_args, \ 14*6777b538SAndroid Build Coastguard Worker run_ffx_command, wait_for_sigterm 15*6777b538SAndroid Build Coastguard Worker 16*6777b538SAndroid Build Coastguard Worker_REPO_NAME = 'chromium-test-package-server' 17*6777b538SAndroid Build Coastguard Worker 18*6777b538SAndroid Build Coastguard Worker 19*6777b538SAndroid Build Coastguard Workerdef _stop_serving(repo_name: str, target: Optional[str]) -> None: 20*6777b538SAndroid Build Coastguard Worker """Stop serving a repository.""" 21*6777b538SAndroid Build Coastguard Worker 22*6777b538SAndroid Build Coastguard Worker # Attempt to clean up. 23*6777b538SAndroid Build Coastguard Worker run_ffx_command( 24*6777b538SAndroid Build Coastguard Worker cmd=['target', 'repository', 'deregister', '-r', repo_name], 25*6777b538SAndroid Build Coastguard Worker target_id=target, 26*6777b538SAndroid Build Coastguard Worker check=False) 27*6777b538SAndroid Build Coastguard Worker run_ffx_command(cmd=['repository', 'remove', repo_name], check=False) 28*6777b538SAndroid Build Coastguard Worker run_ffx_command(cmd=['repository', 'server', 'stop'], check=False) 29*6777b538SAndroid Build Coastguard Worker 30*6777b538SAndroid Build Coastguard Worker 31*6777b538SAndroid Build Coastguard Workerdef _start_serving(repo_dir: str, repo_name: str, 32*6777b538SAndroid Build Coastguard Worker target: Optional[str]) -> None: 33*6777b538SAndroid Build Coastguard Worker """Start serving a repository to a target device. 34*6777b538SAndroid Build Coastguard Worker 35*6777b538SAndroid Build Coastguard Worker Args: 36*6777b538SAndroid Build Coastguard Worker repo_dir: directory the repository is served from. 37*6777b538SAndroid Build Coastguard Worker repo_name: repository name. 38*6777b538SAndroid Build Coastguard Worker target: Fuchsia device the repository is served to. 39*6777b538SAndroid Build Coastguard Worker """ 40*6777b538SAndroid Build Coastguard Worker 41*6777b538SAndroid Build Coastguard Worker run_ffx_command(cmd=('config', 'set', 'repository.server.mode', '\"ffx\"')) 42*6777b538SAndroid Build Coastguard Worker 43*6777b538SAndroid Build Coastguard Worker run_ffx_command(cmd=['repository', 'server', 'start']) 44*6777b538SAndroid Build Coastguard Worker run_ffx_command( 45*6777b538SAndroid Build Coastguard Worker cmd=['repository', 'add-from-pm', repo_dir, '-r', repo_name]) 46*6777b538SAndroid Build Coastguard Worker run_ffx_command(cmd=[ 47*6777b538SAndroid Build Coastguard Worker 'target', 'repository', 'register', '-r', repo_name, '--alias', 48*6777b538SAndroid Build Coastguard Worker REPO_ALIAS 49*6777b538SAndroid Build Coastguard Worker ], 50*6777b538SAndroid Build Coastguard Worker target_id=target) 51*6777b538SAndroid Build Coastguard Worker 52*6777b538SAndroid Build Coastguard Worker 53*6777b538SAndroid Build Coastguard Workerdef register_serve_args(arg_parser: argparse.ArgumentParser) -> None: 54*6777b538SAndroid Build Coastguard Worker """Register common arguments for repository serving.""" 55*6777b538SAndroid Build Coastguard Worker 56*6777b538SAndroid Build Coastguard Worker serve_args = arg_parser.add_argument_group('serve', 57*6777b538SAndroid Build Coastguard Worker 'repo serving arguments') 58*6777b538SAndroid Build Coastguard Worker serve_args.add_argument('--serve-repo', 59*6777b538SAndroid Build Coastguard Worker dest='repo', 60*6777b538SAndroid Build Coastguard Worker help='Directory the repository is served from.') 61*6777b538SAndroid Build Coastguard Worker serve_args.add_argument('--repo-name', 62*6777b538SAndroid Build Coastguard Worker default=_REPO_NAME, 63*6777b538SAndroid Build Coastguard Worker help='Name of the repository.') 64*6777b538SAndroid Build Coastguard Worker 65*6777b538SAndroid Build Coastguard Worker 66*6777b538SAndroid Build Coastguard Workerdef run_serve_cmd(cmd: str, args: argparse.Namespace) -> None: 67*6777b538SAndroid Build Coastguard Worker """Helper for running serve commands.""" 68*6777b538SAndroid Build Coastguard Worker 69*6777b538SAndroid Build Coastguard Worker if cmd == 'start': 70*6777b538SAndroid Build Coastguard Worker _start_serving(args.repo, args.repo_name, args.target_id) 71*6777b538SAndroid Build Coastguard Worker elif cmd == 'stop': 72*6777b538SAndroid Build Coastguard Worker _stop_serving(args.repo_name, args.target_id) 73*6777b538SAndroid Build Coastguard Worker else: 74*6777b538SAndroid Build Coastguard Worker assert cmd == 'run' 75*6777b538SAndroid Build Coastguard Worker catch_sigterm() 76*6777b538SAndroid Build Coastguard Worker with serve_repository(args): 77*6777b538SAndroid Build Coastguard Worker # Clients can assume the repo is up and running once the repo-name 78*6777b538SAndroid Build Coastguard Worker # is printed out. 79*6777b538SAndroid Build Coastguard Worker print(args.repo_name, flush=True) 80*6777b538SAndroid Build Coastguard Worker wait_for_sigterm('shutting down the repo server.') 81*6777b538SAndroid Build Coastguard Worker 82*6777b538SAndroid Build Coastguard Worker 83*6777b538SAndroid Build Coastguard Worker@contextlib.contextmanager 84*6777b538SAndroid Build Coastguard Workerdef serve_repository(args: argparse.Namespace) -> Iterator[None]: 85*6777b538SAndroid Build Coastguard Worker """Context manager for serving a repository.""" 86*6777b538SAndroid Build Coastguard Worker run_serve_cmd('start', args) 87*6777b538SAndroid Build Coastguard Worker try: 88*6777b538SAndroid Build Coastguard Worker yield None 89*6777b538SAndroid Build Coastguard Worker finally: 90*6777b538SAndroid Build Coastguard Worker run_serve_cmd('stop', args) 91*6777b538SAndroid Build Coastguard Worker 92*6777b538SAndroid Build Coastguard Worker 93*6777b538SAndroid Build Coastguard Workerdef main(): 94*6777b538SAndroid Build Coastguard Worker """Stand-alone function for serving a repository.""" 95*6777b538SAndroid Build Coastguard Worker 96*6777b538SAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 97*6777b538SAndroid Build Coastguard Worker parser.add_argument('cmd', 98*6777b538SAndroid Build Coastguard Worker choices=['start', 'stop', 'run'], 99*6777b538SAndroid Build Coastguard Worker help='Choose to start|stop|run repository serving. ' \ 100*6777b538SAndroid Build Coastguard Worker '"start" command will start the repo and exit; ' \ 101*6777b538SAndroid Build Coastguard Worker '"run" command will start the repo and wait ' \ 102*6777b538SAndroid Build Coastguard Worker 'until ctrl-c or sigterm.') 103*6777b538SAndroid Build Coastguard Worker register_device_args(parser) 104*6777b538SAndroid Build Coastguard Worker register_serve_args(parser) 105*6777b538SAndroid Build Coastguard Worker args = parser.parse_args() 106*6777b538SAndroid Build Coastguard Worker if (args.cmd == 'start' or args.cmd == 'run') and not args.repo: 107*6777b538SAndroid Build Coastguard Worker raise ValueError('Directory the repository is serving from needs ' 108*6777b538SAndroid Build Coastguard Worker 'to be specified.') 109*6777b538SAndroid Build Coastguard Worker 110*6777b538SAndroid Build Coastguard Worker run_serve_cmd(args.cmd, args) 111*6777b538SAndroid Build Coastguard Worker 112*6777b538SAndroid Build Coastguard Worker 113*6777b538SAndroid Build Coastguard Workerif __name__ == '__main__': 114*6777b538SAndroid Build Coastguard Worker sys.exit(main()) 115