Add opt-in shell lint and format targets
Introduce make lint-shell / fmt-shell with shellcheck and shfmt (-i 2 -ci -bn), normalize first-party scripts, and document the new targets. Keep them out of make lint / fmt. Signed-off-by: Ludovic Vielle <ludovic@probo.com>
This commit is contained in:
@@ -15,55 +15,53 @@ GO_VERSION="1.26.5"
|
||||
NODE_MAJOR=24
|
||||
NPM_VERSION="11.8.0"
|
||||
|
||||
GOTESTSUM_VERSION="v1.13.0"
|
||||
GOLANGCI_LINT_VERSION="v2.11.3"
|
||||
GOW_VERSION="v0.0.0-20260225145757-ff0f6779ab4c"
|
||||
MKCERT_VERSION="v1.4.4"
|
||||
|
||||
apt-get update -qq
|
||||
apt-get install -y -qq \
|
||||
build-essential \
|
||||
git \
|
||||
curl \
|
||||
jq \
|
||||
parallel \
|
||||
ca-certificates \
|
||||
gnupg \
|
||||
lsb-release \
|
||||
postgresql-client
|
||||
build-essential \
|
||||
git \
|
||||
curl \
|
||||
jq \
|
||||
parallel \
|
||||
ca-certificates \
|
||||
gnupg \
|
||||
lsb-release \
|
||||
postgresql-client
|
||||
|
||||
if ! command -v docker &>/dev/null; then
|
||||
install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
|
||||
| gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
|
||||
| gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
|
||||
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
|
||||
| tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
| tee /etc/apt/sources.list.d/docker.list >/dev/null
|
||||
|
||||
apt-get update -qq
|
||||
apt-get install -y -qq \
|
||||
docker-ce \
|
||||
docker-ce-cli \
|
||||
containerd.io \
|
||||
docker-buildx-plugin \
|
||||
docker-compose-plugin
|
||||
apt-get update -qq
|
||||
apt-get install -y -qq \
|
||||
docker-ce \
|
||||
docker-ce-cli \
|
||||
containerd.io \
|
||||
docker-buildx-plugin \
|
||||
docker-compose-plugin
|
||||
|
||||
systemctl enable --now docker
|
||||
systemctl enable --now docker
|
||||
fi
|
||||
|
||||
usermod -aG docker "${LIMA_CIDATA_USER:-lima}" 2>/dev/null || true
|
||||
|
||||
if [ ! -d "/usr/local/go" ] || ! /usr/local/go/bin/go version | grep -q "go${GO_VERSION}"; then
|
||||
rm -rf /usr/local/go
|
||||
ARCH=$(dpkg --print-architecture)
|
||||
curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${ARCH}.tar.gz" \
|
||||
| tar -C /usr/local -xzf -
|
||||
rm -rf /usr/local/go
|
||||
ARCH=$(dpkg --print-architecture)
|
||||
curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${ARCH}.tar.gz" \
|
||||
| tar -C /usr/local -xzf -
|
||||
fi
|
||||
|
||||
cat > /etc/profile.d/go.sh << 'GOEOF'
|
||||
cat >/etc/profile.d/go.sh <<'GOEOF'
|
||||
export PATH="/usr/local/go/bin:$HOME/go/bin:$PATH"
|
||||
GOEOF
|
||||
chmod +x /etc/profile.d/go.sh
|
||||
@@ -74,14 +72,14 @@ export HOME="${HOME:-/root}"
|
||||
GOBIN=/usr/local/bin /usr/local/go/bin/go install "github.com/mitranim/gow@${GOW_VERSION}"
|
||||
|
||||
if ! command -v node &>/dev/null || ! node --version | grep -q "v${NODE_MAJOR}"; then
|
||||
curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | bash -
|
||||
apt-get install -y -qq nodejs
|
||||
curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | bash -
|
||||
apt-get install -y -qq nodejs
|
||||
fi
|
||||
|
||||
npm install -g "npm@${NPM_VERSION}"
|
||||
|
||||
if ! command -v mkcert &>/dev/null; then
|
||||
GOBIN=/usr/local/bin /usr/local/go/bin/go install "filippo.io/mkcert@${MKCERT_VERSION}"
|
||||
GOBIN=/usr/local/bin /usr/local/go/bin/go install "filippo.io/mkcert@${MKCERT_VERSION}"
|
||||
fi
|
||||
mkcert -install 2>/dev/null || true
|
||||
|
||||
@@ -102,34 +100,35 @@ mkdir -p /etc/probod
|
||||
|
||||
OAUTH2_SIGNING_KEY_PATH=/etc/probod/oauth2-signing-key.pem
|
||||
if [ ! -f "${OAUTH2_SIGNING_KEY_PATH}" ]; then
|
||||
openssl genrsa -out "${OAUTH2_SIGNING_KEY_PATH}" 2048
|
||||
chmod 600 "${OAUTH2_SIGNING_KEY_PATH}"
|
||||
openssl genrsa -out "${OAUTH2_SIGNING_KEY_PATH}" 2048
|
||||
chmod 600 "${OAUTH2_SIGNING_KEY_PATH}"
|
||||
fi
|
||||
|
||||
# Load developer-specific overrides (not committed to repo).
|
||||
if [ -f /workspace/.sandbox.env ]; then
|
||||
set -a
|
||||
. /workspace/.sandbox.env
|
||||
set +a
|
||||
set -a
|
||||
# shellcheck source=/dev/null
|
||||
. /workspace/.sandbox.env
|
||||
set +a
|
||||
fi
|
||||
|
||||
PROBOD_BASE_URL="http://${VM_IP}:8080" \
|
||||
PROBOD_AUTH_COOKIE_DOMAIN="${VM_IP}" \
|
||||
PROBOD_AUTH_COOKIE_SECURE=false \
|
||||
PROBOD_AUTH_COOKIE_SECRET="this-is-a-secure-secret-for-cookie-signing-at-least-32-bytes" \
|
||||
PROBOD_AUTH_PASSWORD_PEPPER="this-is-a-secure-pepper-for-password-hashing-at-least-32-bytes" \
|
||||
PROBOD_ENCRYPTION_KEY="thisisnotasecretAAAAAAAAAAAAAAAAAAAAAAAAAAA=" \
|
||||
PROBOD_OAUTH2_SERVER_SIGNING_KEY="$(cat "${OAUTH2_SIGNING_KEY_PATH}")" \
|
||||
PROBOD_API_CORS_ALLOWED_ORIGINS="http://${VM_IP}:8080,http://${VM_IP}:5173,http://${VM_IP}:5174" \
|
||||
PROBOD_AWS_ENDPOINT="http://127.0.0.1:8333" \
|
||||
PROBOD_AWS_ACCESS_KEY_ID="probod" \
|
||||
PROBOD_AWS_SECRET_ACCESS_KEY="thisisnotasecret" \
|
||||
PROBOD_AWS_USE_PATH_STYLE=true \
|
||||
PROBOD_ACME_DIRECTORY="https://127.0.0.1:9000/acme/acme/directory" \
|
||||
PROBOD_ACME_EMAIL="admin@probo.com" \
|
||||
PROBOD_ACME_KEY_TYPE="EC256" \
|
||||
PROBOD_ACME_ROOT_CA="$(cat /workspace/compose/step-ca/certs/root_ca.crt)" \
|
||||
/workspace/bin/probod-bootstrap -output /etc/probod/config.yml
|
||||
PROBOD_AUTH_COOKIE_DOMAIN="${VM_IP}" \
|
||||
PROBOD_AUTH_COOKIE_SECURE=false \
|
||||
PROBOD_AUTH_COOKIE_SECRET="this-is-a-secure-secret-for-cookie-signing-at-least-32-bytes" \
|
||||
PROBOD_AUTH_PASSWORD_PEPPER="this-is-a-secure-pepper-for-password-hashing-at-least-32-bytes" \
|
||||
PROBOD_ENCRYPTION_KEY="thisisnotasecretAAAAAAAAAAAAAAAAAAAAAAAAAAA=" \
|
||||
PROBOD_OAUTH2_SERVER_SIGNING_KEY="$(cat "${OAUTH2_SIGNING_KEY_PATH}")" \
|
||||
PROBOD_API_CORS_ALLOWED_ORIGINS="http://${VM_IP}:8080,http://${VM_IP}:5173,http://${VM_IP}:5174" \
|
||||
PROBOD_AWS_ENDPOINT="http://127.0.0.1:8333" \
|
||||
PROBOD_AWS_ACCESS_KEY_ID="probod" \
|
||||
PROBOD_AWS_SECRET_ACCESS_KEY="thisisnotasecret" \
|
||||
PROBOD_AWS_USE_PATH_STYLE=true \
|
||||
PROBOD_ACME_DIRECTORY="https://127.0.0.1:9000/acme/acme/directory" \
|
||||
PROBOD_ACME_EMAIL="admin@probo.com" \
|
||||
PROBOD_ACME_KEY_TYPE="EC256" \
|
||||
PROBOD_ACME_ROOT_CA="$(cat /workspace/compose/step-ca/certs/root_ca.crt)" \
|
||||
/workspace/bin/probod-bootstrap -output /etc/probod/config.yml
|
||||
|
||||
# probod runs as ${LIMA_USER} but bootstrap writes config.yml as root with 0600
|
||||
# because it contains secrets. Transfer ownership so probod can read it.
|
||||
@@ -137,7 +136,7 @@ chown "${LIMA_USER}:${LIMA_USER}" /etc/probod/config.yml "${OAUTH2_SIGNING_KEY_P
|
||||
|
||||
# Bind-mount VM-local node_modules over the shared workspace to avoid
|
||||
# platform conflicts between macOS host and Linux VM native binaries.
|
||||
cat > /etc/systemd/system/probo-node-modules.service << EOF
|
||||
cat >/etc/systemd/system/probo-node-modules.service <<EOF
|
||||
[Unit]
|
||||
Description=Bind-mount VM-local node_modules over workspace
|
||||
DefaultDependencies=no
|
||||
@@ -167,11 +166,11 @@ su - "${LIMA_USER}" -c "cd /workspace && npm ci"
|
||||
make -C /workspace generate WITH_APPS=1
|
||||
make -C /workspace embed
|
||||
|
||||
echo "VITE_API_URL=http://${VM_IP}:8080" > /workspace/apps/console/.env
|
||||
echo "VITE_API_URL=http://${VM_IP}:8080" > /workspace/apps/compliance-portal/.env
|
||||
echo "VITE_API_URL=http://${VM_IP}:8080" >/workspace/apps/console/.env
|
||||
echo "VITE_API_URL=http://${VM_IP}:8080" >/workspace/apps/compliance-portal/.env
|
||||
|
||||
# Install systemd services for the sandbox
|
||||
cat > /etc/systemd/system/probo-stack.service << EOF
|
||||
cat >/etc/systemd/system/probo-stack.service <<EOF
|
||||
[Unit]
|
||||
Description=Probo Docker Compose Stack
|
||||
Requires=docker.service
|
||||
@@ -191,7 +190,7 @@ RestartSec=5s
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
cat > /etc/systemd/system/probod.service << EOF
|
||||
cat >/etc/systemd/system/probod.service <<EOF
|
||||
[Unit]
|
||||
Description=Probo API Server
|
||||
Requires=probo-stack.service
|
||||
@@ -211,7 +210,7 @@ Environment=PATH=/usr/local/go/bin:/usr/local/bin:/usr/bin:/bin
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
cat > /etc/systemd/system/probo-console.service << EOF
|
||||
cat >/etc/systemd/system/probo-console.service <<EOF
|
||||
[Unit]
|
||||
Description=Probo Console Dev Server
|
||||
Requires=probo-node-modules.service
|
||||
@@ -229,7 +228,7 @@ RestartSec=3s
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
cat > /etc/systemd/system/probo-compliance-portal.service << EOF
|
||||
cat >/etc/systemd/system/probo-compliance-portal.service <<EOF
|
||||
[Unit]
|
||||
Description=Probo Compliance Portal Dev Server
|
||||
Requires=probo-node-modules.service
|
||||
|
||||
@@ -12,7 +12,7 @@ WORKTREE_NAME="$(basename "${REPO_ROOT}")"
|
||||
VM_NAME="probo-${WORKTREE_NAME}"
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
cat <<EOF
|
||||
Usage: $(basename "$0") <command> [options]
|
||||
|
||||
Commands:
|
||||
@@ -29,151 +29,166 @@ Commands:
|
||||
|
||||
VM name: ${VM_NAME} (derived from worktree directory)
|
||||
EOF
|
||||
exit 1
|
||||
exit 1
|
||||
}
|
||||
|
||||
get_vm_ip() {
|
||||
limactl shell "${VM_NAME}" ip -4 -j addr show dev lima0 2>/dev/null \
|
||||
| jq -r '.[0].addr_info[0].local // empty' 2>/dev/null || true
|
||||
limactl shell "${VM_NAME}" ip -4 -j addr show dev lima0 2>/dev/null \
|
||||
| jq -r '.[0].addr_info[0].local // empty' 2>/dev/null || true
|
||||
}
|
||||
|
||||
get_vm_status() {
|
||||
local status
|
||||
status=$(limactl list --json 2>/dev/null \
|
||||
| jq -r "select(.name == \"${VM_NAME}\") | .status" 2>/dev/null) || true
|
||||
echo "${status:-NotFound}"
|
||||
local status
|
||||
status=$(limactl list --json 2>/dev/null \
|
||||
| jq -r "select(.name == \"${VM_NAME}\") | .status" 2>/dev/null) || true
|
||||
echo "${status:-NotFound}"
|
||||
}
|
||||
|
||||
cmd_create() {
|
||||
local cpus="" memory="" disk=""
|
||||
local cpus="" memory="" disk=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--cpus) cpus="$2"; shift 2 ;;
|
||||
--memory) memory="$2"; shift 2 ;;
|
||||
--disk) disk="$2"; shift 2 ;;
|
||||
*) echo "Unknown option: $1"; usage ;;
|
||||
esac
|
||||
done
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--cpus)
|
||||
cpus="$2"
|
||||
shift 2
|
||||
;;
|
||||
--memory)
|
||||
memory="$2"
|
||||
shift 2
|
||||
;;
|
||||
--disk)
|
||||
disk="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "Creating sandbox: ${VM_NAME}"
|
||||
echo "Worktree: ${REPO_ROOT}"
|
||||
echo "Creating sandbox: ${VM_NAME}"
|
||||
echo "Worktree: ${REPO_ROOT}"
|
||||
|
||||
local -a create_args=(
|
||||
--name "${VM_NAME}"
|
||||
--tty=false
|
||||
--set ".mounts = [{\"location\": \"${REPO_ROOT}\", \"mountPoint\": \"/workspace\", \"writable\": true},{\"location\": \"${HOME}/go\", \"mountPoint\": \"/home/${USER}.guest/go\", \"writable\": true}]"
|
||||
--mount-type virtiofs
|
||||
)
|
||||
local -a create_args=(
|
||||
--name "${VM_NAME}"
|
||||
--tty=false
|
||||
--set ".mounts = [{\"location\": \"${REPO_ROOT}\", \"mountPoint\": \"/workspace\", \"writable\": true},{\"location\": \"${HOME}/go\", \"mountPoint\": \"/home/${USER}.guest/go\", \"writable\": true}]"
|
||||
--mount-type virtiofs
|
||||
)
|
||||
|
||||
if [[ -n "${cpus}" ]]; then
|
||||
create_args+=(--cpus "${cpus}")
|
||||
fi
|
||||
if [[ -n "${memory}" ]]; then
|
||||
create_args+=(--memory "${memory}")
|
||||
fi
|
||||
if [[ -n "${disk}" ]]; then
|
||||
create_args+=(--disk "${disk}")
|
||||
fi
|
||||
if [[ -n "${cpus}" ]]; then
|
||||
create_args+=(--cpus "${cpus}")
|
||||
fi
|
||||
if [[ -n "${memory}" ]]; then
|
||||
create_args+=(--memory "${memory}")
|
||||
fi
|
||||
if [[ -n "${disk}" ]]; then
|
||||
create_args+=(--disk "${disk}")
|
||||
fi
|
||||
|
||||
limactl create "${create_args[@]}" "${TEMPLATE}"
|
||||
limactl create "${create_args[@]}" "${TEMPLATE}"
|
||||
}
|
||||
|
||||
cmd_start() {
|
||||
echo "Starting sandbox: ${VM_NAME}"
|
||||
limactl start "${VM_NAME}"
|
||||
echo ""
|
||||
cmd_status
|
||||
echo "Starting sandbox: ${VM_NAME}"
|
||||
limactl start "${VM_NAME}"
|
||||
echo ""
|
||||
cmd_status
|
||||
}
|
||||
|
||||
cmd_boot_logs() {
|
||||
limactl shell "${VM_NAME}" -- sudo tail -f /var/log/cloud-init-output.log
|
||||
limactl shell "${VM_NAME}" -- sudo tail -f /var/log/cloud-init-output.log
|
||||
}
|
||||
|
||||
cmd_stop() {
|
||||
echo "Stopping sandbox: ${VM_NAME}"
|
||||
limactl stop "${VM_NAME}"
|
||||
echo "Sandbox stopped."
|
||||
echo "Stopping sandbox: ${VM_NAME}"
|
||||
limactl stop "${VM_NAME}"
|
||||
echo "Sandbox stopped."
|
||||
}
|
||||
|
||||
cmd_restart() {
|
||||
cmd_stop
|
||||
echo ""
|
||||
cmd_start
|
||||
cmd_stop
|
||||
echo ""
|
||||
cmd_start
|
||||
}
|
||||
|
||||
cmd_delete() {
|
||||
echo "Deleting sandbox: ${VM_NAME}"
|
||||
limactl delete --force "${VM_NAME}"
|
||||
echo "Sandbox deleted."
|
||||
echo "Deleting sandbox: ${VM_NAME}"
|
||||
limactl delete --force "${VM_NAME}"
|
||||
echo "Sandbox deleted."
|
||||
}
|
||||
|
||||
cmd_ssh() {
|
||||
exec limactl shell --workdir /workspace "${VM_NAME}"
|
||||
exec limactl shell --workdir /workspace "${VM_NAME}"
|
||||
}
|
||||
|
||||
cmd_exec() {
|
||||
limactl shell --workdir /workspace "${VM_NAME}" "$@"
|
||||
limactl shell --workdir /workspace "${VM_NAME}" "$@"
|
||||
}
|
||||
|
||||
cmd_status() {
|
||||
local status ip
|
||||
status="$(get_vm_status)"
|
||||
ip="$(get_vm_ip)"
|
||||
local status ip
|
||||
status="$(get_vm_status)"
|
||||
ip="$(get_vm_ip)"
|
||||
|
||||
echo "Sandbox: ${VM_NAME}"
|
||||
echo "State: ${status}"
|
||||
echo "IP: ${ip:-"-"}"
|
||||
echo "Sandbox: ${VM_NAME}"
|
||||
echo "State: ${status}"
|
||||
echo "IP: ${ip:-"-"}"
|
||||
|
||||
if [[ "${status}" == "Running" && -n "${ip}" ]]; then
|
||||
echo ""
|
||||
echo "Services (use VM IP to access from host):"
|
||||
echo " Console: http://${ip}:5173"
|
||||
echo " Compliance Portal: http://${ip}:5174"
|
||||
echo " API: http://${ip}:8080"
|
||||
echo " Grafana: http://${ip}:3001"
|
||||
echo " Mailpit: http://${ip}:8025"
|
||||
echo " Keycloak: http://${ip}:8082"
|
||||
echo " PostgreSQL: psql -h ${ip} -U probod"
|
||||
fi
|
||||
if [[ "${status}" == "Running" && -n "${ip}" ]]; then
|
||||
echo ""
|
||||
echo "Services (use VM IP to access from host):"
|
||||
echo " Console: http://${ip}:5173"
|
||||
echo " Compliance Portal: http://${ip}:5174"
|
||||
echo " API: http://${ip}:8080"
|
||||
echo " Grafana: http://${ip}:3001"
|
||||
echo " Mailpit: http://${ip}:8025"
|
||||
echo " Keycloak: http://${ip}:8082"
|
||||
echo " PostgreSQL: psql -h ${ip} -U probod"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_list() {
|
||||
printf "%-25s %-12s %s\n" "NAME" "STATE" "IP"
|
||||
printf "%-25s %-12s %s\n" "NAME" "STATE" "IP"
|
||||
|
||||
limactl list --json 2>/dev/null | jq -r '
|
||||
limactl list --json 2>/dev/null | jq -r '
|
||||
select(.name | startswith("probo-")) |
|
||||
[.name, .status] | @tsv
|
||||
' | while IFS=$'\t' read -r name status; do
|
||||
local ip="-"
|
||||
if [[ "${status}" == "Running" ]]; then
|
||||
ip=$(limactl shell "${name}" ip -4 -j addr show dev lima0 2>/dev/null \
|
||||
| jq -r '.[0].addr_info[0].local // "-"' 2>/dev/null || echo "-")
|
||||
fi
|
||||
printf "%-25s %-12s %s\n" "${name}" "${status}" "${ip}"
|
||||
done
|
||||
local ip="-"
|
||||
if [[ "${status}" == "Running" ]]; then
|
||||
ip=$(limactl shell "${name}" ip -4 -j addr show dev lima0 2>/dev/null \
|
||||
| jq -r '.[0].addr_info[0].local // "-"' 2>/dev/null || echo "-")
|
||||
fi
|
||||
printf "%-25s %-12s %s\n" "${name}" "${status}" "${ip}"
|
||||
done
|
||||
}
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
usage
|
||||
usage
|
||||
fi
|
||||
|
||||
command="$1"
|
||||
shift
|
||||
|
||||
case "${command}" in
|
||||
create) cmd_create "$@" ;;
|
||||
start) cmd_start ;;
|
||||
boot-logs) cmd_boot_logs ;;
|
||||
stop) cmd_stop ;;
|
||||
restart) cmd_restart ;;
|
||||
delete) cmd_delete ;;
|
||||
ssh) cmd_ssh ;;
|
||||
exec)
|
||||
if [[ "${1:-}" == "--" ]]; then shift; fi
|
||||
cmd_exec "$@"
|
||||
;;
|
||||
status) cmd_status ;;
|
||||
list) cmd_list ;;
|
||||
*) echo "Unknown command: ${command}"; usage ;;
|
||||
create) cmd_create "$@" ;;
|
||||
start) cmd_start ;;
|
||||
boot-logs) cmd_boot_logs ;;
|
||||
stop) cmd_stop ;;
|
||||
restart) cmd_restart ;;
|
||||
delete) cmd_delete ;;
|
||||
ssh) cmd_ssh ;;
|
||||
exec)
|
||||
if [[ "${1:-}" == "--" ]]; then shift; fi
|
||||
cmd_exec "$@"
|
||||
;;
|
||||
status) cmd_status ;;
|
||||
list) cmd_list ;;
|
||||
*)
|
||||
echo "Unknown command: ${command}"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
Reference in New Issue
Block a user