diff --git a/base/container_scripts/install_phelpers.sh b/base/container_scripts/install_phelpers.sh new file mode 100644 index 0000000..f7a7a1a --- /dev/null +++ b/base/container_scripts/install_phelpers.sh @@ -0,0 +1,88 @@ +# The p-helper commands, back and better than ever! +# This file should be sourced to get the classic commands inside your oci-env + + +_paction() { + SERVICES=$(s6-rc -d list | grep -E 'pulpcore|nginx' | paste -sd ' ') + if [ $# -gt 1 ] ; then + SERVICES="${@:2}" + fi + echo "`setterm -foreground blue` s6-rc $1 ${SERVICES}" + setterm -default + s6-rc $1 ${SERVICES} +} + +pstart() { + _paction start $@ +} +_pstart_help="Start all pulp-related services" + +pstop() { + _paction stop $@ +} +_pstop_help="Stop all pulp-related services" + +prestart() { + _paction stop $@ + _paction start $@ +} +_prestart_help="Restart all pulp-related services" + +pstatus() { + echo "`setterm -foreground green`Services that are live/ran successfully" + _paction -a list + echo "`setterm -foreground red`Services that are down" + _paction -da list +} +_pstatus_help="Report the status of all pulp-related services" + + +pdbreset() { + echo "Resetting the Pulp database" + bash /opt/oci_env/base/container_scripts/database_reset.sh +} +_pdbreset_help="Reset the Pulp database" +# can get away with not resetting terminal settings here since it gets reset in phelp +_pdbreset_help="$_dbreset_help - `setterm -foreground red -bold on`THIS DESTROYS YOUR PULP DATA" + +pclean() { + pdbreset + sudo rm -rf /var/pulp/media/* + redis-cli FLUSHALL + pulpcore-manager collectstatic --clear --noinput --link + if which mc ; then + mc rb --force s3/${PULP_AWS_STORAGE_BUCKET_NAME} + mc mb s3/${PULP_AWS_STORAGE_BUCKET_NAME} + fi +} +_pclean_help="Restore pulp to a clean-installed state" +# can get away with not resetting terminal settings here since it gets reset in phelp +_pclean_help="$_pclean_help - `setterm -foreground red -bold on`THIS DESTROYS YOUR PULP DATA" + +phelp() { + # get a list of declared functions, filter out ones with leading underscores as "private" + funcs=$(declare -F | awk '{ print $3 }'| grep -v ^_ | grep -v fzf) + + # for each func, if a help string is defined, assume it's a pulp function and print its help + # (this is bash introspection via variable variables) + for func in $funcs; do + # get the "help" variable name for this function + help_var="_${func}_help" + # use ${!} syntax to eval the help_var + help=${!help_var} + # If the help var had a value, echo its value here (the value is function help text) + if [ ! -z "$help" ]; then + # make the function name easy to spot + setterm -foreground yellow -bold on + echo -n "$func" + # reset terminal formatting before printing the help text + # (implicitly format it as normal text) + setterm -default + echo ": $help" + fi + done + + # explicitly restore terminal formatting is reset before exiting function + setterm -default +} +_phelp_help="Print this help" \ No newline at end of file diff --git a/base/init.sh b/base/init.sh index b2d5b38..3b8ac86 100755 --- a/base/init.sh +++ b/base/init.sh @@ -11,6 +11,10 @@ then then echo "eval \"\$(LC_ALL=C _PULP_COMPLETE=bash_source pulp)\"" >> /root/.bashrc fi + if ! grep -q "install_phelpers.sh" /root/.bashrc + then + echo "source /opt/oci_env/base/container_scripts/install_phelpers.sh" >> /root/.bashrc + fi pulp --refresh-api status fi diff --git a/base/s6-rc-modifications/pulpcore-api/run b/base/s6-rc-modifications/pulpcore-api/run deleted file mode 100755 index 8f4b6f9..0000000 --- a/base/s6-rc-modifications/pulpcore-api/run +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/execlineb -S0 -s6-setuidgid pulp -foreground { - /database/assets/wait_on_database_migrations.sh -} -foreground { - export DJANGO_SETTINGS_MODULE pulpcore.app.settings - export PULP_CONTENT_ORIGIN localhost - /usr/local/bin/pulpcore-manager collectstatic --clear --noinput --link -} -export DJANGO_SETTINGS_MODULE pulpcore.app.settings -export PULP_SETTINGS /etc/pulp/settings.py -export HOME /var/lib/pulp/ - -# TODO: Modify OCI base image to allow for auto reload to be configurable so we don't have to override this. -/usr/local/bin/gunicorn pulpcore.app.wsgi:application --bind "127.0.0.1:24817" --name pulp-api --access-logfile - --access-logformat "pulp [%({correlation-id}o)s]: %(h)s %(l)s %(u)s %(t)s \"%(r)s\" %(s)s %(b)s \"%(f)s\" \"%(a)s\"" --reload diff --git a/client/oci_env/commands.py b/client/oci_env/commands.py index 60fae07..4e012c8 100644 --- a/client/oci_env/commands.py +++ b/client/oci_env/commands.py @@ -200,3 +200,35 @@ def poll(args, client): def pulp(args, client): exit(client.exec(["pulp"] + args.command, interactive=False).returncode) + + +def phelper(args, client): + if args.action in ("help", "status", "dbreset", "clean"): + proc = client.exec(["bash", "-lc", f"p{args.action}"], shell=True) + exit(proc.returncode) + shortcuts = {"api": "pulpcore-api", "content": "pulpcore-content"} + pcmd = [f"p{args.action}"] + opts = set(args.services) + for val in opts: + if val in shortcuts: + pcmd.append(shortcuts[val]) + elif val.startswith("worker"): + # Support notation: 'worker', 'worker3', 'worker1-3' + worker_range = [int(i) for i in val[len("worker"):].split("-") if i.isdigit()] + if len(worker_range) == 1: + worker_range.append(worker_range[0]) + elif len(worker_range) == 0: + worker_range = [1, int(client.config.get("PULP_WORKERS", 2))] + worker_range[1] += 1 # Increase outer bounds for range + for i in range(*worker_range[:3]): + pcmd.append(f"pulpcore-worker@{i}") + else: + pcmd.append(val) + + if args.action in {"start", "restart"}: + if set(pcmd).intersection({"pulpcore-api", "pulpcore-content"}) and "nginx" not in opts: + pcmd.append("nginx") + cmd_str = " ".join(pcmd) + print(f"{args.action.capitalize()}ing {pcmd[1:] or 'all services'}") + proc = client.exec(["bash", "-lc", f'"{cmd_str}"'], shell=True) + exit(proc.returncode) diff --git a/client/oci_env/main.py b/client/oci_env/main.py index 44af19c..3d1d569 100644 --- a/client/oci_env/main.py +++ b/client/oci_env/main.py @@ -11,7 +11,8 @@ pulpcore_manager, profile, poll, - pulp + pulp, + phelper ) from oci_env.utils import ( @@ -55,6 +56,7 @@ def get_parser(): parse_profile_command(subparsers) parse_poll_command(subparsers) parse_pulp_cli_command(subparsers) + parse_phelper_commands(subparsers) return parser @@ -154,6 +156,20 @@ def parse_pulp_cli_command(subparsers): parser.set_defaults(func=pulp) +def parse_phelper_commands(subparsers): + for action in ("start", "stop", "restart"): + parser = subparsers.add_parser(f'p{action}', help=f'{action.capitalize()} all/any Pulp service') + parser.add_argument('services', nargs=argparse.REMAINDER, help=f'List of services to {action}, leave blank to {action} all') + parser.set_defaults(func=phelper, action=action) + parser = subparsers.add_parser('phelp', help='Show available pcommands available in the container.') + parser.set_defaults(func=phelper, action="help") + parser = subparsers.add_parser('pstatus', help='Return the status of pulp-related services.') + parser.set_defaults(func=phelper, action="status") + parser = subparsers.add_parser('pclean', help='Restore Pulp to a clean install state.') + parser.set_defaults(func=phelper, action="clean") + parser = subparsers.add_parser('pdbreset', help='Reset the Pulp database.') + parser.set_defaults(func=phelper, action="dbreset") + def main(): parser = get_parser() args = parser.parse_args() diff --git a/client/oci_env/utils.py b/client/oci_env/utils.py index d9c9eca..6a85f36 100644 --- a/client/oci_env/utils.py +++ b/client/oci_env/utils.py @@ -412,7 +412,7 @@ def _service_containers(): except subprocess.CalledProcessError: _exit_no_container_found() - def exec(self, args, service=None, interactive=False, pipe_output=False, privileged=False): + def exec(self, args, service=None, interactive=False, pipe_output=False, privileged=False, shell=False): """ Execute a script in a running container using podman or docker. @@ -432,15 +432,17 @@ def exec(self, args, service=None, interactive=False, pipe_output=False, privile if privileged: cmd = cmd[:2] + ["--privileged"] + cmd[2:] + if shell: + cmd = " ".join(cmd) if interactive: if self.is_verbose: logger.info(f"Running [interactive] command in container: {' '.join(cmd)}") - proc = subprocess.call(cmd) + proc = subprocess.call(cmd, shell=shell) else: if self.is_verbose: logger.info(f"Running [non-interactive] command in container: {' '.join(cmd)}") - proc = subprocess.run(cmd, capture_output=pipe_output) + proc = subprocess.run(cmd, capture_output=pipe_output, shell=shell) return proc def get_dynaconf_variable(self, name):