dx/dxkit/runtime/native.runtime.sh

222 lines
No EOL
6.1 KiB
Bash

#!/usr/bin/env bash
# dxkit/runtime/native.runtime.sh
#
# Native runtime driver — runs services directly on the host
# without containerization. Supports macOS (Homebrew) and Linux (systemd).
#
# To activate:
# export RUNTIME_DRIVER=native # in globals.env or local.env
# export NATIVE_WEB_SERVER=apache # apache | nginx (auto-detected if unset)
#
# Requirements:
# macOS — Homebrew, httpd or nginx, php
# Linux — systemd, apache2 or nginx, php-fpm
# ============================================
# Platform + web server detection
# ============================================
function runtime::native::_platform() {
case "$(uname -s)" in
Darwin) echo "macos" ;;
Linux) echo "linux" ;;
*)
log::error "Unsupported platform: $(uname -s)"
return 1
;;
esac
}
function runtime::native::_webserver() {
if [[ -n "${NATIVE_WEB_SERVER:-}" ]]; then
echo "$NATIVE_WEB_SERVER"
return
fi
local platform
platform="$(runtime::native::_platform)"
if [[ "$platform" == "macos" ]]; then
brew list httpd &>/dev/null && echo "apache" && return
brew list nginx &>/dev/null && echo "nginx" && return
else
systemctl list-unit-files apache2.service &>/dev/null && echo "apache" && return
systemctl list-unit-files nginx.service &>/dev/null && echo "nginx" && return
fi
log::error "No supported web server found (apache2 / nginx)"
log::error "Install one or set NATIVE_WEB_SERVER=apache|nginx"
return 1
}
# ============================================
# Service management — platform dispatch
# ============================================
function runtime::native::_service_start() {
local service="$1"
case "$(runtime::native::_platform)" in
macos) brew services start "$service" ;;
linux) sudo systemctl start "$service" ;;
esac
}
function runtime::native::_service_stop() {
local service="$1"
case "$(runtime::native::_platform)" in
macos) brew services stop "$service" ;;
linux) sudo systemctl stop "$service" ;;
esac
}
function runtime::native::_service_running() {
local service="$1"
case "$(runtime::native::_platform)" in
macos) brew services list | awk -v s="$service" '$1==s{print $2}' | grep -q "started" ;;
linux) systemctl is-active --quiet "$service" ;;
esac
}
function runtime::native::_service_logs() {
local service="$1"
case "$(runtime::native::_platform)" in
macos)
local log_dir
log_dir="$(brew --prefix)/var/log"
tail -f "${log_dir}/${service}/error.log" "${log_dir}/${service}/access.log" 2>/dev/null \
|| tail -f "${log_dir}/${service}.log" 2>/dev/null
;;
linux)
sudo journalctl -u "$service" -f --no-pager
;;
esac
}
# ============================================
# Service name resolution
# ============================================
function runtime::native::_apache_service() {
case "$(runtime::native::_platform)" in
macos) echo "httpd" ;;
linux) echo "apache2" ;;
esac
}
function runtime::native::_nginx_service() { echo "nginx"; }
function runtime::native::_fpm_service() {
local php_ver
php_ver="$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;' 2>/dev/null || echo "8.3")"
case "$(runtime::native::_platform)" in
macos) echo "php@${php_ver}" ;;
linux) echo "php${php_ver}-fpm" ;;
esac
}
function runtime::native::_active_services() {
local ws
ws="$(runtime::native::_webserver)"
case "$ws" in
apache) echo "$(runtime::native::_apache_service)" ;;
nginx) echo "$(runtime::native::_fpm_service)"
echo "$(runtime::native::_nginx_service)" ;;
esac
}
# ============================================
# Interface implementation
# ============================================
function runtime::native::up() {
log::info "Starting native runtime ($(runtime::native::_webserver))..."
local service
while IFS= read -r service; do
runtime::native::_service_start "$service"
done < <(runtime::native::_active_services)
log::success "Stack up"
}
function runtime::native::down() {
log::info "Stopping native runtime..."
# Stop in reverse order
local services=()
while IFS= read -r service; do
services+=("$service")
done < <(runtime::native::_active_services)
for ((i=${#services[@]}-1; i>=0; i--)); do
runtime::native::_service_stop "${services[i]}"
done
}
function runtime::native::ensure() {
local service
while IFS= read -r service; do
if ! runtime::native::_service_running "$service"; then
runtime::native::_service_start "$service"
fi
done < <(runtime::native::_active_services)
}
function runtime::native::logs() {
local ws
ws="$(runtime::native::_webserver)"
case "$ws" in
apache)
runtime::native::_service_logs "$(runtime::native::_apache_service)"
;;
nginx)
runtime::native::_service_logs "$(runtime::native::_nginx_service)"
;;
esac
}
function runtime::native::list() {
printf "%-25s %s\n" "SERVICE" "STATUS"
printf "%-25s %s\n" "-------" "------"
local service
while IFS= read -r service; do
if runtime::native::_service_running "$service"; then
printf "%-25s %s\n" "$service" "running"
else
printf "%-25s %s\n" "$service" "stopped"
fi
done < <(runtime::native::_active_services)
}
function runtime::native::status() {
printf "%-20s %s\n" "Driver:" "native"
printf "%-20s %s\n" "Platform:" "$(runtime::native::_platform)"
printf "%-20s %s\n" "Web server:" "$(runtime::native::_webserver)"
printf "%-20s %s\n" "App root:" "$(ctx::root)"
echo ""
runtime::native::list
}
function runtime::native::build() {
# Native has no images to build — but vhost generation still needs to happen
log::info "Native runtime has no build step (services run directly)"
log::info "Reload configs with: dx proxy restart"
}
function runtime::native::is_inside() {
# Native always runs on host — there's no "inside" concept
return 1
}
function runtime::native::exec() {
# No container boundary — run directly in the app root
cd "$(ctx::root)" && "$@"
}
function runtime::native::shell() {
cd "$(ctx::root)" && exec "${SHELL:-bash}"
}