Commit a9add541 by Bambang Adrian

fix(osrm): release v3.8 fundamental filename logic fix

parent c9b26f67
Ketika Anda menggunakan Docker, file-file yang ada di dalam
image Docker tidak dapat diubah secara langsung setelah image dibuat. Untuk memodifikasi leaflet_options.js, Anda harus membuat image Docker kustom yang menggantikan file asli dengan versi yang sudah Anda ubah. Anda dapat melakukan ini dengan bantuan Dockerfile dan mengelola semuanya dengan docker-compose.yml.
Berikut adalah panduan langkah demi langkah untuk menerapkan perubahan ini menggunakan Docker Compose.
Langkah 1: Siapkan semua file
Pertama, Anda perlu mengumpulkan semua file yang diperlukan di satu direktori proyek Anda.
Struktur direktori:
my-osrm-project/
├── docker-compose.yml
├── leaflet_options.js
├── Dockerfile.frontend
└── (direktori data, misalnya ./data untuk .osrm files)
Penjelasan:
docker-compose.yml: File utama untuk mendefinisikan dan menjalankan layanan multi-kontainer Anda.
leaflet_options.js: File ini adalah versi kustom dari src/leaflet_options.js dari repositori osrm-frontend. Di sinilah Anda akan mendefinisikan profil rute yang berbeda.
Dockerfile.frontend: File ini digunakan untuk membuat image Docker kustom untuk frontend Anda.
data: Direktori lokal tempat Anda menyimpan semua file .osm.pbf dan .osrm yang sudah diproses.
Langkah 2: Buat file leaflet_options.js kustom
Buat file baru bernama leaflet_options.js di direktori proyek Anda, dan isi dengan konfigurasi untuk setiap profil yang Anda inginkan.
Isi file leaflet_options.js:
javascript
// leaflet_options.js
module.exports = {
services: [
{
label: 'Mobil (Tercepat)',
path: 'http://backend-car:5000/route/v1' // Ganti dengan nama service backend mobil
},
{
label: 'Sepeda (Tercepat)',
path: 'http://backend-bike:5000/route/v1' // Ganti dengan nama service backend sepeda
},
{
label: 'Jalan Kaki (Tercepat)',
path: 'http://backend-foot:5000/route/v1' // Ganti dengan nama service backend jalan kaki
}
],
center: [ -6.2, 106.8 ], // Koordinat pusat peta (contoh untuk Jakarta)
zoom: 13,
// Tambahkan opsi konfigurasi lain di sini jika diperlukan
};
Gunakan kode dengan hati-hati.
Penting: Perhatikan bahwa path mengarah ke nama layanan Docker (misalnya, backend-car) yang akan didefinisikan di docker-compose.yml, bukan localhost.
Langkah 3: Buat Dockerfile kustom untuk frontend
Buat file baru bernama Dockerfile.frontend untuk membuat image Docker frontend kustom Anda.
Isi file Dockerfile.frontend:
dockerfile
# Gunakan image osrm-frontend resmi sebagai basis
FROM osrm/osrm-frontend:latest
# Salin file leaflet_options.js kustom Anda ke dalam direktori src
COPY leaflet_options.js src/leaflet_options.js
# Kompilasi ulang aset frontend dengan konfigurasi baru
RUN npm run compile
Gunakan kode dengan hati-hati.
COPY akan menimpa file asli di dalam image dengan versi kustom Anda. Perintah RUN npm run compile memastikan bahwa semua aset JavaScript diperbarui dengan perubahan konfigurasi Anda.
Langkah 4: Tulis file docker-compose.yml
Buat docker-compose.yml yang akan menyatukan semua layanan (backend dan frontend) yang berbeda.
Isi file docker-compose.yml:
yaml
version: '3.7'
services:
# OSRM Backend untuk profil Mobil
backend-car:
image: osrm/osrm-backend:latest
container_name: osrm_backend_car
volumes:
- ./data:/data
command: osrm-routed --algorithm mld /data/indonesia-latest-car.osrm
ports:
- "5000:5000" # Tetap menggunakan port 5000 di dalam container
restart: always
# OSRM Backend untuk profil Sepeda
backend-bike:
image: osrm/osrm-backend:latest
container_name: osrm_backend_bike
volumes:
- ./data:/data
command: osrm-routed --algorithm mld /data/indonesia-latest-bike.osrm
ports:
- "5001:5000" # Mapping ke port 5001 di host
restart: always
# OSRM Backend untuk profil Jalan Kaki
backend-foot:
image: osrm/osrm-backend:latest
container_name: osrm_backend_foot
volumes:
- ./data:/data
command: osrm-routed --algorithm mld /data/indonesia-latest-foot.osrm
ports:
- "5002:5000" # Mapping ke port 5002 di host
restart: always
# Frontend menggunakan image kustom
frontend:
build:
context: .
dockerfile: Dockerfile.frontend
container_name: osrm_frontend
ports:
- "9966:9966"
depends_on:
- backend-car
- backend-bike
- backend-foot
restart: always
Gunakan kode dengan hati-hati.
Penjelasan penting:
build: Menunjuk ke direktori saat ini (.) dan Dockerfile.frontend untuk membuat image kustom.
volumes: Pastikan semua backend mengacu pada direktori data yang sama.
ports: Backend berjalan pada port 5000 di dalam setiap kontainer, tetapi dipetakan ke port yang berbeda di host untuk menghindari konflik. Frontend tidak perlu terhubung ke port host ini karena ia berkomunikasi dengan nama layanan backend (misalnya backend-car) di jaringan Docker.
depends_on: Memastikan bahwa semua backend sudah berjalan sebelum frontend mencoba untuk memulai.
Langkah 5: Jalankan Docker Compose
Dari direktori proyek Anda, jalankan perintah berikut di terminal:
bash
# Lakukan proses data terlebih dahulu (extract, partition, customize)
# Perintah ini akan memakan waktu.
docker compose run --rm backend-car osrm-extract -p /opt/car.lua /data/indonesia-latest.osm.pbf
docker compose run --rm backend-car osrm-partition /data/indonesia-latest.osrm
docker compose run --rm backend-car osrm-customize /data/indonesia-latest.osrm
# Lakukan hal yang sama untuk profil sepeda dan jalan kaki
docker compose run --rm backend-bike osrm-extract -p /opt/bicycle.lua /data/indonesia-latest.osm.pbf
# ... dan seterusnya ...
# Jalankan semua layanan
docker compose up --build -d
Gunakan kode dengan hati-hati.
Setelah semua kontainer berjalan, Anda bisa mengakses frontend Anda di http://localhost:9966. Anda akan melihat dropdown dengan profil rute yang telah Anda definisikan.
\ No newline at end of file
diff --git a/scripts/install-osrm-ngpm.sh b/scripts/install-osrm-ngpm.sh
index bde75a6..c02ed76 100755
--- a/scripts/install-osrm-ngpm.sh
+++ b/scripts/install-osrm-ngpm.sh
@@ -2,7 +2,7 @@
#
# install-osrm-ngpm.sh
# OSRM + NGPM installer & manager (Rocky Linux 10)
-# Final self-contained script (v2.6 - Final Cleanup & Readability)
+# Final self-contained script (v2.7 - Correct Skip-Preprocessing Check)
#
set -euo pipefail
IFS=$'\n\t'
@@ -52,10 +52,17 @@ LOGFILE=""
PROFILE_ARR=()
# -------------------------
-# Logging helpers (unchanged)
+# Logging helpers
# -------------------------
timestamp() { date '+%Y-%m-%d %H:%M:%S'; }
-_log() { local lvl="$1"; shift; local ts; ts="$(timestamp)"; if [[ -n "${LOGFILE:-}" ]]; then printf "%s [%s] %s\n" "$ts" "$lvl" "$*" >> "${LOGFILE}"; fi; printf "%s [%s] %s\n" "$ts" "$lvl" "$*"; }
+_log() {
+ local lvl="$1"; shift
+ local ts; ts="$(timestamp)"
+ if [[ -n "${LOGFILE:-}" ]]; then
+ printf "%s [%s] %s\n" "$ts" "$lvl" "$*" >> "${LOGFILE}"
+ fi
+ printf "%s [%s] %s\n" "$ts" "$lvl" "$*"
+}
info() { _log "INFO" "$*"; }
success() { _log "SUCCESS" "$*"; }
warn() { _log "WARN" "$*"; }
@@ -133,21 +140,89 @@ parse_args() {
}
# -------------------------
-# Helper Functions (unchanged)
+# Helper Functions
# -------------------------
command_exists() { command -v "$1" >/dev/null 2>&1; }
-prereqs_check() { info "Running prerequisite checks..."; local ok=0; if ! command_exists docker; then err "Docker is not installed."; ok=1; fi; if ! docker compose version >/dev/null 2>&1; then err "Docker Compose V2 plugin is not installed."; ok=1; fi; if ! command_exists curl; then err "curl is not installed."; ok=1; fi; if [ ${ok} -ne 0 ]; then err "Prerequisite checks failed."; exit 1; fi; success "All prerequisites are met."; }
-SELINUX_LABEL=""; setup_selinux_flag() { if command_exists sestatus && sestatus 2>/dev/null | grep -qi "SELinux status:.*enabled"; then SELINUX_LABEL=",z"; info "SELinux is enabled. Appending ',z' to volume mounts."; fi; }
-ask_confirm() { local prompt="$1"; if [ "${yes_all}" = true ]; then info "[auto-yes] ${prompt} -> yes"; return 0; fi; while true; do printf "%s [y/N]: " "${prompt}"; read -r yn; case "${yn}" in [Yy]*) return 0 ;; [Nn]*|"") return 1 ;; *) echo "Please answer y or n." ;; esac; done; }
+prereqs_check() {
+ info "Running prerequisite checks..."
+ local ok=0
+ if ! command_exists docker; then err "Docker is not installed."; ok=1; fi
+ if ! docker compose version >/dev/null 2>&1; then err "Docker Compose V2 plugin is not installed."; ok=1; fi
+ if ! command_exists curl; then err "curl is not installed."; ok=1; fi
+ if [ ${ok} -ne 0 ]; then err "Prerequisite checks failed."; exit 1; fi
+ success "All prerequisites are met."
+}
+SELINUX_LABEL="";
+setup_selinux_flag() {
+ if command_exists sestatus && sestatus 2>/dev/null | grep -qi "SELinux status:.*enabled"; then
+ SELINUX_LABEL=",z"
+ info "SELinux is enabled. Appending ',z' to volume mounts."
+ fi
+}
+ask_confirm() {
+ local prompt="$1"
+ if [ "${yes_all}" = true ]; then info "[auto-yes] ${prompt} -> yes"; return 0; fi
+ while true; do
+ printf "%s [y/N]: " "${prompt}"
+ read -r yn
+ case "${yn}" in
+ [Yy]*) return 0 ;;
+ [Nn]*|"") return 1 ;;
+ *) echo "Please answer y or n." ;;
+ esac
+ done
+}
# -------------------------
# Core Logic
# -------------------------
-download_map() { info "Preparing map from source: ${map_source}"; local map_instance_dir="${work_dir}/${map_name}/dataset"; mkdir -p "${map_instance_dir}"; MAP_PATH="${map_instance_dir}/$(basename "${map_source}")"; if [[ -f "${MAP_PATH}" ]]; then info "Map file already exists. Skipping download."; return 0; fi; if [[ "${map_source}" =~ ^https?:// ]]; then if [ "${dry_run}" = true ]; then warn "[DRY RUN] Would download map to ${MAP_PATH}"; return 0; fi; info "Downloading map with curl..."; if ! curl -L --fail -o "${MAP_PATH}.tmp" "${map_source}"; then rm -f "${MAP_PATH}.tmp"; err "Download failed."; exit 1; fi; mv "${MAP_PATH}.tmp" "${MAP_PATH}"; success "Map downloaded successfully."; elif [[ -f "${map_source}" ]]; then if [ "${dry_run}" = true ]; then warn "[DRY RUN] Would copy local map to ${MAP_PATH}"; return 0; fi; info "Copying local map file..."; cp -v "${map_source}" "${MAP_PATH}"; success "Local map copied."; else err "Map source '${map_source}' is not a valid URL or an existing file."; exit 1; fi; }
-generate_profiles() { info "Generating profile files for map instance '${map_name}'"; local profile_dir="${work_dir}/${map_name}/profiles"; local patched_dir="${work_dir}/${map_name}/patched-profiles"; mkdir -p "${profile_dir}" "${patched_dir}"; for profile in "${PROFILE_ARR[@]}"; do local pf="${profile_dir}/${profile}.lua"; if [ ! -f "${pf}" ]; then case "${profile}" in car|bicycle|bike|foot) info "Generating wrapper for built-in profile: ${profile}"; cat > "${pf}" <<LUA
+download_map() {
+ info "Preparing map from source: ${map_source}"
+ local map_instance_dir="${work_dir}/${map_name}/dataset"
+ mkdir -p "${map_instance_dir}"
+ MAP_PATH="${map_instance_dir}/$(basename "${map_source}")"
+ if [[ -f "${MAP_PATH}" ]]; then
+ info "Map file already exists. Skipping download."
+ return 0
+ fi
+ if [[ "${map_source}" =~ ^https?:// ]]; then
+ if [ "${dry_run}" = true ]; then warn "[DRY RUN] Would download map to ${MAP_PATH}"; return 0; fi
+ info "Downloading map with curl..."
+ if ! curl -L --fail -o "${MAP_PATH}.tmp" "${map_source}"; then
+ rm -f "${MAP_PATH}.tmp"
+ err "Download failed."
+ exit 1
+ fi
+ mv "${MAP_PATH}.tmp" "${MAP_PATH}"
+ success "Map downloaded successfully."
+ elif [[ -f "${map_source}" ]]; then
+ if [ "${dry_run}" = true ]; then warn "[DRY RUN] Would copy local map to ${MAP_PATH}"; return 0; fi
+ info "Copying local map file..."
+ cp -v "${map_source}" "${MAP_PATH}"
+ success "Local map copied."
+ else
+ err "Map source '${map_source}' is not a valid URL or an existing file."
+ exit 1
+ fi
+}
+generate_profiles() {
+ info "Generating profile files for map instance '${map_name}'"
+ local profile_dir="${work_dir}/${map_name}/profiles"
+ local patched_dir="${work_dir}/${map_name}/patched-profiles"
+ mkdir -p "${profile_dir}" "${patched_dir}"
+ for profile in "${PROFILE_ARR[@]}"; do
+ local pf="${profile_dir}/${profile}.lua"
+ if [ ! -f "${pf}" ]; then
+ case "${profile}" in
+ car|bicycle|bike|foot)
+ info "Generating wrapper for built-in profile: ${profile}"
+ cat > "${pf}" <<LUA
return dofile('/opt/${profile}.lua')
LUA
- ;; motorcycle) info "Generating custom 'motorcycle' profile based on 'car'"; cat > "${pf}" <<'LUA'
+ ;;
+ motorcycle)
+ info "Generating custom 'motorcycle' profile based on 'car'"
+ cat > "${pf}" <<'LUA'
local car_module = dofile('/opt/car.lua')
local profile = car_module.setup()
profile.properties.max_speed = 100
@@ -157,12 +232,28 @@ profile.restrictions["toll"] = "prohibited"
car_module.setup = function() return profile end
return car_module
LUA
- ;; *) warn "No generator for profile '${profile}'."; continue;; esac; fi; cp "${pf}" "${patched_dir}/${profile}.lua"; done; success "Profile generation complete."; }
+ ;;
+ *)
+ warn "No generator for profile '${profile}'."
+ continue
+ ;;
+ esac
+ fi
+ cp "${pf}" "${patched_dir}/${profile}.lua"
+ done
+ success "Profile generation complete."
+}
generate_docker_compose() {
info "Generating Docker Compose file: ${COMPOSE_FILE}"
- local map_instance_dir="${work_dir}/${map_name}"; local selabel="${SELINUX_LABEL:-}"; local services=""; local idx=0
+ local map_instance_dir="${work_dir}/${map_name}"
+ local selabel="${SELINUX_LABEL:-}"
+ local services=""
+ local idx=0
for profile in "${PROFILE_ARR[@]}"; do
- idx=$((idx+1)); local host_port=$((backend_port + idx - 1)); local pdata="${map_instance_dir}/${profile}-data"; mkdir -p "${pdata}"
+ idx=$((idx + 1))
+ local host_port=$((backend_port + idx - 1))
+ local pdata="${map_instance_dir}/${profile}-data"
+ mkdir -p "${pdata}"
services+="
osrm-preprocess-${map_name}-${profile}:
image: ${DEFAULT_BACKEND_REGISTRY}:${DEFAULT_BACKEND_VERSION}
@@ -188,12 +279,19 @@ generate_docker_compose() {
- ${network_name}
"
done
- local frontend_block=""; if [ "${no_frontend}" != true ]; then
+ local frontend_block=""
+ if [ "${no_frontend}" != true ]; then
if [ -z "${mapbox_token}" ]; then
- warn "Mapbox token not provided. The frontend map may not render. Use --mapbox-token <your_token>."
+ warn "Mapbox token not provided. The frontend map may not render."
fi
- local backend_urls=""; local idx2=0
- for profile in "${PROFILE_ARR[@]}"; do idx2=$((idx2+1)); local host_port=$((backend_port + idx2 - 1)); local url="http://${backend_domain}:${host_port}${backend_path}/${api_version}/${profile}"; backend_urls+="${url},"; done
+ local backend_urls=""
+ local idx2=0
+ for profile in "${PROFILE_ARR[@]}"; do
+ idx2=$((idx2 + 1))
+ local host_port=$((backend_port + idx2 - 1))
+ local url="http://${backend_domain}:${host_port}${backend_path}/${api_version}/${profile}"
+ backend_urls+="${url},"
+ done
backend_urls=${backend_urls%,}
frontend_block+="
osrm-frontend-${map_name}:
@@ -224,15 +322,29 @@ EOF
# -------------------------
run_install() {
info "Starting OSRM installation for map instance: '${map_name}'"
- if [ -f "${COMPOSE_FILE}" ] && ! ask_confirm "Instance '${map_name}' may exist. Re-running will update config and recreate containers. Continue?"; then info "Installation aborted."; exit 0; fi
- download_map; generate_profiles; generate_docker_compose
- if [ "${dry_run}" = true ]; then warn "[DRY RUN] Skipping network and container startup."; return; fi
- info "Ensuring Docker network '${network_name}' exists..."; docker network create "${network_name}" >/dev/null 2>&1 || info "Network already exists."
- info "Pulling latest Docker images..."; docker pull "${DEFAULT_BACKEND_REGISTRY}:${DEFAULT_BACKEND_VERSION}"; if [[ "${no_frontend}" != "true" ]]; then docker pull "${DEFAULT_FRONTEND_REGISTRY}:${DEFAULT_FRONTEND_VERSION}"; fi
+ if [ -f "${COMPOSE_FILE}" ] && ! ask_confirm "Instance '${map_name}' may exist. Re-running will update config and recreate containers. Continue?"; then
+ info "Installation aborted."
+ exit 0
+ fi
+ download_map
+ generate_profiles
+ generate_docker_compose
+ if [ "${dry_run}" = true ]; then
+ warn "[DRY RUN] Skipping network and container startup."
+ return
+ fi
+ info "Ensuring Docker network '${network_name}' exists..."
+ docker network create "${network_name}" >/dev/null 2>&1 || info "Network already exists."
+ info "Pulling latest Docker images..."
+ docker pull "${DEFAULT_BACKEND_REGISTRY}:${DEFAULT_BACKEND_VERSION}"
+ if [[ "${no_frontend}" != "true" ]]; then
+ docker pull "${DEFAULT_FRONTEND_REGISTRY}:${DEFAULT_FRONTEND_VERSION}"
+ fi
local needs_preprocessing=false
for profile in "${PROFILE_ARR[@]}"; do
local pdata_dir="${work_dir}/${map_name}/${profile}-data"
- if [ ! -f "${pdata_dir}/map.osrm" ]; then
+ # FIX (v2.7): Check for the .properties file, which is a reliable indicator of completion for MLD.
+ if [ ! -f "${pdata_dir}/map.osrm.properties" ]; then
needs_preprocessing=true
break
fi
@@ -241,25 +353,33 @@ run_install() {
info "Starting data preprocessing for missing profiles..."
for profile in "${PROFILE_ARR[@]}"; do
local pdata_dir="${work_dir}/${map_name}/${profile}-data"
- if [ -f "${pdata_dir}/map.osrm" ]; then
+ # FIX (v2.7): Same check here.
+ if [ -f "${pdata_dir}/map.osrm.properties" ]; then
info "--- Skipping profile '${profile}', data already exists. ---"
continue
fi
- info "Preparing map file for profile '${profile}'..."; cp -vf "${MAP_PATH}" "${pdata_dir}/map.osm.pbf"
+ info "Preparing map file for profile '${profile}'..."
+ cp -vf "${MAP_PATH}" "${pdata_dir}/map.osm.pbf"
local service_name="osrm-preprocess-${map_name}-${profile}"
info "--- Processing profile: ${profile} ---"
if docker compose -f "${COMPOSE_FILE}" up --build --exit-code-from "${service_name}" "${service_name}"; then
success "Preprocessing for '${profile}' completed."
else
- err "Preprocessing for '${profile}' FAILED. Check logs for details."; if ! ask_confirm "Continue with other profiles?"; then err "Aborting installation."; exit 1; fi
+ err "Preprocessing for '${profile}' FAILED. Check logs for details."
+ if ! ask_confirm "Continue with other profiles?"; then
+ err "Aborting installation."
+ exit 1
+ fi
fi
docker compose -f "${COMPOSE_FILE}" rm -fsv "${service_name}" >/dev/null 2>&1 || true
done
else
info "All profile data already exists, skipping preprocessing."
fi
- info "Starting all services for instance '${map_name}'..."; docker compose -f "${COMPOSE_FILE}" up -d --remove-orphans
- success "Installation for '${map_name}' completed!"; print_summary
+ info "Starting all services for instance '${map_name}'..."
+ docker compose -f "${COMPOSE_FILE}" up -d --remove-orphans
+ success "Installation for '${map_name}' completed!"
+ print_summary
}
run_update() {
info "Starting update for instance '${map_name}', component '${sub_command}'"
@@ -268,36 +388,36 @@ run_update() {
exit 1
fi
case "${sub_command}" in
- backend|frontend|all)
- info "Pulling latest images..."
- docker pull "${DEFAULT_BACKEND_REGISTRY}:${DEFAULT_BACKEND_VERSION}"
- if [[ "${sub_command}" != "backend" ]]; then
- docker pull "${DEFAULT_FRONTEND_REGISTRY}:${DEFAULT_FRONTEND_VERSION}"
- fi
- info "Recreating services..."
- docker compose -f "${COMPOSE_FILE}" up -d --remove-orphans
- ;;
- map|profile)
- if [[ "${sub_command}" == "map" ]]; then
- download_map
- fi
- generate_profiles
- info "Re-running preprocessing..."
- for profile in "${PROFILE_ARR[@]}"; do
- local pdata_dir="${work_dir}/${map_name}/${profile}-data"
- info "Preparing map file for profile '${profile}'..."
- cp -vf "${MAP_PATH}" "${pdata_dir}/map.osm.pbf"
- local service_name="osrm-preprocess-${map_name}-${profile}"
- docker compose -f "${COMPOSE_FILE}" up --build --exit-code-from "${service_name}" "${service_name}" || err "Preprocessing failed for ${profile}"
- docker compose -f "${COMPOSE_FILE}" rm -fsv "${service_name}" >/dev/null 2>&1 || true
- done
- info "Restarting services..."
- docker compose -f "${COMPOSE_FILE}" up -d --remove-orphans
- ;;
- *)
- err "Invalid update component."
- exit 1
- ;;
+ backend | frontend | all)
+ info "Pulling latest images..."
+ docker pull "${DEFAULT_BACKEND_REGISTRY}:${DEFAULT_BACKEND_VERSION}"
+ if [[ "${sub_command}" != "backend" ]]; then
+ docker pull "${DEFAULT_FRONTEND_REGISTRY}:${DEFAULT_FRONTEND_VERSION}"
+ fi
+ info "Recreating services..."
+ docker compose -f "${COMPOSE_FILE}" up -d --remove-orphans
+ ;;
+ map | profile)
+ if [[ "${sub_command}" == "map" ]]; then
+ download_map
+ fi
+ generate_profiles
+ info "Re-running preprocessing..."
+ for profile in "${PROFILE_ARR[@]}"; do
+ local pdata_dir="${work_dir}/${map_name}/${profile}-data"
+ info "Preparing map file for profile '${profile}'..."
+ cp -vf "${MAP_PATH}" "${pdata_dir}/map.osm.pbf"
+ local service_name="osrm-preprocess-${map_name}-${profile}"
+ docker compose -f "${COMPOSE_FILE}" up --build --exit-code-from "${service_name}" "${service_name}" || err "Preprocessing failed for ${profile}"
+ docker compose -f "${COMPOSE_FILE}" rm -fsv "${service_name}" >/dev/null 2>&1 || true
+ done
+ info "Restarting services..."
+ docker compose -f "${COMPOSE_FILE}" up -d --remove-orphans
+ ;;
+ *)
+ err "Invalid update component."
+ exit 1
+ ;;
esac
success "Update for '${map_name}' completed."
}
@@ -350,10 +470,10 @@ main() {
info "Starting script execution."
info "Command: ${command_name}, Map Instance: ${map_name}"
case "${command_name}" in
- install) run_install ;;
- update) run_update ;;
- remove) run_remove ;;
- *) err "Unknown command: ${command_name}"; usage ;;
+ install) run_install ;;
+ update) run_update ;;
+ remove) run_remove ;;
+ *) err "Unknown command: ${command_name}"; usage ;;
esac
info "Script execution finished."
}
......@@ -2,7 +2,7 @@
#
# install-osrm-ngpm.sh
# OSRM + NGPM installer & manager (Rocky Linux 10)
# Final self-contained script (v2.7 - Correct Skip-Preprocessing Check)
# Final self-contained script (v3.8 - Fundamental Filename Logic Fix)
#
set -euo pipefail
IFS=$'\n\t'
......@@ -24,6 +24,8 @@ DEFAULT_BACKEND_DOMAIN="localhost"
DEFAULT_FRONTEND_DOMAIN="localhost"
DEFAULT_BACKEND_PATH="/osrm"
DEFAULT_API_VERSION="v1"
DEFAULT_MAP_CENTER="-6.2,106.8" # Jakarta
DEFAULT_MAP_ZOOM="13"
# -------------------------
# RUN-TIME VARIABLES
......@@ -40,6 +42,8 @@ frontend_domain="${DEFAULT_FRONTEND_DOMAIN}"
backend_path="${DEFAULT_BACKEND_PATH}"
api_version="${DEFAULT_API_VERSION}"
mapbox_token=""
map_center="${DEFAULT_MAP_CENTER}"
map_zoom="${DEFAULT_MAP_ZOOM}"
no_frontend=false
dry_run=false
yes_all=false
......@@ -55,14 +59,7 @@ PROFILE_ARR=()
# Logging helpers
# -------------------------
timestamp() { date '+%Y-%m-%d %H:%M:%S'; }
_log() {
local lvl="$1"; shift
local ts; ts="$(timestamp)"
if [[ -n "${LOGFILE:-}" ]]; then
printf "%s [%s] %s\n" "$ts" "$lvl" "$*" >> "${LOGFILE}"
fi
printf "%s [%s] %s\n" "$ts" "$lvl" "$*"
}
_log() { local lvl="$1"; shift; local ts; ts="$(timestamp)"; if [[ -n "${LOGFILE:-}" ]]; then printf "%s [%s] %s\n" "$ts" "$lvl" "$*" >> "${LOGFILE}"; fi; printf "%s [%s] %s\n" "$ts" "$lvl" "$*"; }
info() { _log "INFO" "$*"; }
success() { _log "SUCCESS" "$*"; }
warn() { _log "WARN" "$*"; }
......@@ -73,26 +70,24 @@ err() { _log "ERROR" "$*" >&2; }
# -------------------------
usage() {
cat <<EOF
OSRM Installer & Manager v2.7 (Multi-Map Support)
OSRM Installer & Manager v3.8
Usage:
$0 <command> --map-name <name> [options]
Commands:
install Install a new OSRM instance.
update <component> Update a component (backend, frontend, map, profile, all).
install Install or update a full OSRM instance.
update <component> Update a specific component (map, profile, backend, frontend).
remove Remove an OSRM instance.
Required Argument:
--map-name <name> A unique name for this map instance (e.g., 'indonesia').
Options:
--map-source <url|path> Map URL or local file path.
--profiles <csv> Profiles to enable (car,motorcycle,bike,foot).
--mapbox-token <token> (Required for Frontend) Your Mapbox public access token.
--map-center <lat,lon> Initial map center coordinate (default: Jakarta).
--map-zoom <level> Initial map zoom level (default: 13).
--backend-port <port> Host start port for backend services.
--frontend-port <port> Host port for the frontend UI.
--mapbox-token <token> (Required for Frontend) Your Mapbox public access token.
--no-frontend Do NOT install the frontend UI.
--no-frontend Do NOT include the frontend service.
--purge Also delete all data directories on remove.
--dry-run Simulate steps without executing.
--yes Answer 'yes' to all prompts.
......@@ -114,24 +109,22 @@ parse_args() {
while (( "$#" )); do
case "$1" in
--map-name) map_name="$2"; shift 2 ;;
--work-dir) work_dir="${2/#\~/$HOME}"; shift 2 ;;
--map-source) map_source="$2"; shift 2 ;;
--profiles) profiles_csv="$2"; shift 2 ;;
--mapbox-token) mapbox_token="$2"; shift 2 ;;
--map-center) map_center="$2"; shift 2 ;;
--map-zoom) map_zoom="$2"; shift 2 ;;
--backend-port) backend_port="$2"; shift 2 ;;
--frontend-port) frontend_port="$2"; shift 2 ;;
--network) network_name="$2"; shift 2 ;;
--backend-domain) backend_domain="$2"; shift 2 ;;
--frontend-domain) frontend_domain="$2"; shift 2 ;;
--mapbox-token) mapbox_token="$2"; shift 2 ;;
--no-frontend) no_frontend=true; shift ;;
--dry-run) dry_run=true; shift ;;
--purge) do_purge=true; shift ;;
--dry-run) dry_run=true; shift ;;
--yes) yes_all=true; shift ;;
-h|--help) usage ;;
*) err "Unknown option: $1"; usage ;;
esac
done
if [[ "${map_name}" == "default" && "${command_name}" != "install" ]]; then err "The --map-name argument is required."; usage; fi
if [[ "${map_name}" == "default" ]]; then err "The --map-name argument is required."; usage; fi
work_dir="${work_dir/#\~/$HOME}"; local log_dir="${work_dir}/logs"; mkdir -p "${work_dir}" "${log_dir}"
LOGFILE="${log_dir}/osrm-manager-$(date '+%Y%m%d_%H%M%S').log"; : > "${LOGFILE}"
COMPOSE_FILE="${work_dir}/docker-compose.${map_name}.yml"
......@@ -143,35 +136,9 @@ parse_args() {
# Helper Functions
# -------------------------
command_exists() { command -v "$1" >/dev/null 2>&1; }
prereqs_check() {
info "Running prerequisite checks..."
local ok=0
if ! command_exists docker; then err "Docker is not installed."; ok=1; fi
if ! docker compose version >/dev/null 2>&1; then err "Docker Compose V2 plugin is not installed."; ok=1; fi
if ! command_exists curl; then err "curl is not installed."; ok=1; fi
if [ ${ok} -ne 0 ]; then err "Prerequisite checks failed."; exit 1; fi
success "All prerequisites are met."
}
SELINUX_LABEL="";
setup_selinux_flag() {
if command_exists sestatus && sestatus 2>/dev/null | grep -qi "SELinux status:.*enabled"; then
SELINUX_LABEL=",z"
info "SELinux is enabled. Appending ',z' to volume mounts."
fi
}
ask_confirm() {
local prompt="$1"
if [ "${yes_all}" = true ]; then info "[auto-yes] ${prompt} -> yes"; return 0; fi
while true; do
printf "%s [y/N]: " "${prompt}"
read -r yn
case "${yn}" in
[Yy]*) return 0 ;;
[Nn]*|"") return 1 ;;
*) echo "Please answer y or n." ;;
esac
done
}
prereqs_check() { info "Running prerequisite checks..."; local ok=0; if ! command_exists docker; then err "Docker is not installed."; ok=1; fi; if ! docker compose version >/dev/null 2>&1; then err "Docker Compose V2 plugin is not installed."; ok=1; fi; if ! command_exists curl; then err "curl is not installed."; ok=1; fi; if [ ${ok} -ne 0 ]; then err "Prerequisite checks failed."; exit 1; fi; success "All prerequisites are met."; }
SELINUX_LABEL=""; setup_selinux_flag() { if command_exists sestatus && sestatus 2>/dev/null | grep -qi "SELinux status:.*enabled"; then SELINUX_LABEL=",z"; info "SELinux is enabled. Appending ',z' to volume mounts."; fi; }
ask_confirm() { local prompt="$1"; if [ "${yes_all}" = true ]; then info "[auto-yes] ${prompt} -> yes"; return 0; fi; while true; do printf "%s [y/N]: " "${prompt}"; read -r yn; case "${yn}" in [Yy]*) return 0 ;; [Nn]*|"") return 1 ;; *) echo "Please answer y or n." ;; esac; done; }
# -------------------------
# Core Logic
......@@ -181,85 +148,113 @@ download_map() {
local map_instance_dir="${work_dir}/${map_name}/dataset"
mkdir -p "${map_instance_dir}"
MAP_PATH="${map_instance_dir}/$(basename "${map_source}")"
if [[ -f "${MAP_PATH}" ]]; then
info "Map file already exists. Skipping download."
return 0
fi
if [[ -f "${MAP_PATH}" ]]; then info "Map file already exists. Skipping download."; return 0; fi
if [[ "${map_source}" =~ ^https?:// ]]; then
if [ "${dry_run}" = true ]; then warn "[DRY RUN] Would download map to ${MAP_PATH}"; return 0; fi
info "Downloading map with curl..."
if ! curl -L --fail -o "${MAP_PATH}.tmp" "${map_source}"; then
rm -f "${MAP_PATH}.tmp"
err "Download failed."
exit 1
fi
mv "${MAP_PATH}.tmp" "${MAP_PATH}"
success "Map downloaded successfully."
info "Downloading map with curl..."; if ! curl -L --fail -o "${MAP_PATH}.tmp" "${map_source}"; then rm -f "${MAP_PATH}.tmp"; err "Download failed."; exit 1; fi
mv "${MAP_PATH}.tmp" "${MAP_PATH}"; success "Map downloaded successfully."
elif [[ -f "${map_source}" ]]; then
if [ "${dry_run}" = true ]; then warn "[DRY RUN] Would copy local map to ${MAP_PATH}"; return 0; fi
info "Copying local map file..."
cp -v "${map_source}" "${MAP_PATH}"
success "Local map copied."
else
err "Map source '${map_source}' is not a valid URL or an existing file."
exit 1
info "Copying local map file..."; cp -v "${map_source}" "${MAP_PATH}"; success "Local map copied."
else err "Map source '${map_source}' is not a valid URL or an existing file."; exit 1;
fi
}
generate_profiles() {
info "Generating profile files for map instance '${map_name}'"
local profile_dir="${work_dir}/${map_name}/profiles"
local patched_dir="${work_dir}/${map_name}/patched-profiles"
local profile_dir="${work_dir}/${map_name}/profiles"; local patched_dir="${work_dir}/${map_name}/patched-profiles"
mkdir -p "${profile_dir}" "${patched_dir}"
for profile in "${PROFILE_ARR[@]}"; do
local pf="${profile_dir}/${profile}.lua"
if [ ! -f "${pf}" ]; then
case "${profile}" in
car|bicycle|bike|foot)
info "Generating wrapper for built-in profile: ${profile}"
cat > "${pf}" <<LUA
info "Generating wrapper for built-in profile: ${profile}"; cat > "${pf}" <<LUA
return dofile('/opt/${profile}.lua')
LUA
;;
motorcycle)
info "Generating custom 'motorcycle' profile based on 'car'"
cat > "${pf}" <<'LUA'
info "Generating custom 'motorcycle' profile based on 'car'"; cat > "${pf}" <<'LUA'
local car_module = dofile('/opt/car.lua')
local profile = car_module.setup()
profile.properties.max_speed = 100
profile.properties.max_speed = 90
profile.properties.u_turn_penalty = 60
profile.restrictions = profile.restrictions or {}
profile.restrictions["toll"] = "prohibited"
profile.speed_profile["motorway"] = 90
profile.speed_profile["motorway_link"] = 45
car_module.setup = function() return profile end
return car_module
LUA
;;
*)
warn "No generator for profile '${profile}'."
continue
;;
*) warn "No generator for profile '${profile}'. Please create it manually."; continue;;
esac
fi
cp "${pf}" "${patched_dir}/${profile}.lua"
done
success "Profile generation complete."
}
generate_leaflet_options() {
local map_instance_dir="${work_dir}/${map_name}"; local leaflet_options_path="${map_instance_dir}/leaflet_options.js"
info "Generating custom leaflet_options.js for '${map_name}'"
local services_js="services: [\n"; for profile in "${PROFILE_ARR[@]}"; do
local label; label="$(tr '[:lower:]' '[:upper:]' <<< ${profile:0:1})${profile:1}"
local backend_service_name="osrm-routed-${map_name}-${profile}"
services_js+=" {\n label: '${label}',\n path: 'http://${backend_service_name}:5000/route/v1'\n },\n"
done; services_js+=" ],"
cat > "${leaflet_options_path}" <<EOF
module.exports = {
$services_js
center: [ ${map_center} ],
zoom: ${map_zoom}
};
EOF
success "leaflet_options.js generated at ${leaflet_options_path}"
}
generate_frontend_dockerfile() {
local map_instance_dir="${work_dir}/${map_name}"; local dockerfile_path="${map_instance_dir}/Dockerfile.frontend"
info "Generating custom Dockerfile.frontend for '${map_name}'"
cat > "${dockerfile_path}" <<EOF
FROM ${DEFAULT_FRONTEND_REGISTRY}:${DEFAULT_FRONTEND_VERSION}
COPY leaflet_options.js src/leaflet_options.js
RUN npm run compile
EOF
success "Dockerfile.frontend generated at ${dockerfile_path}"
}
generate_docker_compose() {
info "Generating Docker Compose file: ${COMPOSE_FILE}"
local map_instance_dir="${work_dir}/${map_name}"
local selabel="${SELINUX_LABEL:-}"
local services=""
# Start writing the file
cat > "${COMPOSE_FILE}" <<EOF
services:
EOF
# Append backend services
local idx=0
for profile in "${PROFILE_ARR[@]}"; do
idx=$((idx + 1))
local host_port=$((backend_port + idx - 1))
local pdata="${map_instance_dir}/${profile}-data"
# --- FIX IS HERE (v3.8) ---
# 1. Use a clean base name for all operations.
local base_name="${map_name}-${profile}"
# 2. Use this base name for the symlink and all osrm commands.
# 3. This ensures output files are named `indonesia-car.osrm.*` correctly.
mkdir -p "${pdata}"
services+="
cat >> "${COMPOSE_FILE}" <<EOF
osrm-preprocess-${map_name}-${profile}:
image: ${DEFAULT_BACKEND_REGISTRY}:${DEFAULT_BACKEND_VERSION}
container_name: osrm-preprocess-${map_name}-${profile}
command: >
sh -c \"osrm-extract -p /opt/custom_profiles/${profile}.lua /data/map.osm.pbf && osrm-partition /data/map.osrm && osrm-customize /data/map.osrm\"
sh -c 'ln -s map.osm.pbf /data/${base_name}.osm.pbf &&
osrm-extract -p /opt/custom_profiles/${profile}.lua /data/${base_name}.osm.pbf &&
osrm-partition /data/${base_name}.osrm &&
osrm-customize /data/${base_name}.osrm'
volumes:
- ${map_instance_dir}/patched-profiles:/opt/custom_profiles:ro${selabel}
- ${pdata}:/data:rw${selabel}
......@@ -270,45 +265,46 @@ generate_docker_compose() {
image: ${DEFAULT_BACKEND_REGISTRY}:${DEFAULT_BACKEND_VERSION}
container_name: osrm-routed-${map_name}-${profile}
restart: unless-stopped
command: osrm-routed --algorithm mld /data/map.osrm
command: osrm-routed --algorithm mld /data/${base_name}.osrm
volumes:
- ${pdata}:/data:ro${selabel}
ports:
- \"${host_port}:5000\"
- "${host_port}:5000"
networks:
- ${network_name}
"
EOF
done
local frontend_block=""
# Append frontend service
if [ "${no_frontend}" != true ]; then
if [ -z "${mapbox_token}" ]; then
warn "Mapbox token not provided. The frontend map may not render."
fi
local backend_urls=""
local idx2=0
for profile in "${PROFILE_ARR[@]}"; do
idx2=$((idx2 + 1))
local host_port=$((backend_port + idx2 - 1))
local url="http://${backend_domain}:${host_port}${backend_path}/${api_version}/${profile}"
backend_urls+="${url},"
done
backend_urls=${backend_urls%,}
frontend_block+="
if [ -z "${mapbox_token}" ]; then warn "Mapbox token not provided. The frontend map may not render."; fi
cat >> "${COMPOSE_FILE}" <<EOF
osrm-frontend-${map_name}:
image: ${DEFAULT_FRONTEND_REGISTRY}:${DEFAULT_FRONTEND_VERSION}
build:
context: ${map_instance_dir}
dockerfile: Dockerfile.frontend
container_name: osrm-frontend-${map_name}
restart: unless-stopped
environment:
- VITE_DEFAULT_BACKEND_URLS=${backend_urls}
- VITE_MAPBOX_ACCESS_TOKEN=${mapbox_token}
- OSRM_MAPBOX_TOKEN=${mapbox_token}
ports:
- \"${frontend_port}:9966\"
- "${frontend_port}:9966"
networks:
- ${network_name}
"
depends_on:
EOF
for profile in "${PROFILE_ARR[@]}"; do
cat >> "${COMPOSE_FILE}" <<EOF
- osrm-routed-${map_name}-${profile}
EOF
done
fi
cat > "${COMPOSE_FILE}" <<EOF
services:${services}${frontend_block}
# Append networks block
cat >> "${COMPOSE_FILE}" <<EOF
networks:
${network_name}:
external: true
......@@ -322,29 +318,23 @@ EOF
# -------------------------
run_install() {
info "Starting OSRM installation for map instance: '${map_name}'"
if [ -f "${COMPOSE_FILE}" ] && ! ask_confirm "Instance '${map_name}' may exist. Re-running will update config and recreate containers. Continue?"; then
info "Installation aborted."
exit 0
fi
download_map
generate_profiles
generate_docker_compose
if [ "${dry_run}" = true ]; then
warn "[DRY RUN] Skipping network and container startup."
return
fi
info "Ensuring Docker network '${network_name}' exists..."
docker network create "${network_name}" >/dev/null 2>&1 || info "Network already exists."
info "Pulling latest Docker images..."
docker pull "${DEFAULT_BACKEND_REGISTRY}:${DEFAULT_BACKEND_VERSION}"
if [ -f "${COMPOSE_FILE}" ] && ! ask_confirm "Instance '${map_name}' may exist. Re-running will update config and recreate/rebuild containers. Continue?"; then info "Installation aborted."; exit 0; fi
download_map; generate_profiles
if [[ "${no_frontend}" != "true" ]]; then
docker pull "${DEFAULT_FRONTEND_REGISTRY}:${DEFAULT_FRONTEND_VERSION}"
generate_leaflet_options; generate_frontend_dockerfile
fi
generate_docker_compose
if [ "${dry_run}" = true ]; then warn "[DRY RUN] Skipping network and container startup."; return; fi
info "Ensuring Docker network '${network_name}' exists..."; docker network create "${network_name}" >/dev/null 2>&1 || info "Network already exists."
info "Pulling latest base Docker images..."; docker pull "${DEFAULT_BACKEND_REGISTRY}:${DEFAULT_BACKEND_VERSION}"; if [[ "${no_frontend}" != "true" ]]; then docker pull "${DEFAULT_FRONTEND_REGISTRY}:${DEFAULT_FRONTEND_VERSION}"; fi
local needs_preprocessing=false
for profile in "${PROFILE_ARR[@]}"; do
local pdata_dir="${work_dir}/${map_name}/${profile}-data"
# FIX (v2.7): Check for the .properties file, which is a reliable indicator of completion for MLD.
if [ ! -f "${pdata_dir}/map.osrm.properties" ]; then
# --- FIX IS HERE (v3.8) ---
# Use the correct base name to check for the properties file.
local base_name="${map_name}-${profile}"
if [ ! -f "${pdata_dir}/${base_name}.osrm.properties" ]; then
needs_preprocessing=true
break
fi
......@@ -353,122 +343,89 @@ run_install() {
info "Starting data preprocessing for missing profiles..."
for profile in "${PROFILE_ARR[@]}"; do
local pdata_dir="${work_dir}/${map_name}/${profile}-data"
# FIX (v2.7): Same check here.
if [ -f "${pdata_dir}/map.osrm.properties" ]; then
local base_name="${map_name}-${profile}"
if [ -f "${pdata_dir}/${base_name}.osrm.properties" ]; then
info "--- Skipping profile '${profile}', data already exists. ---"
continue
fi
info "Preparing map file for profile '${profile}'..."
cp -vf "${MAP_PATH}" "${pdata_dir}/map.osm.pbf"
info "Preparing map file for profile '${profile}'..."; cp -vf "${MAP_PATH}" "${pdata_dir}/map.osm.pbf"
local service_name="osrm-preprocess-${map_name}-${profile}"
info "--- Processing profile: ${profile} ---"
if docker compose -f "${COMPOSE_FILE}" up --build --exit-code-from "${service_name}" "${service_name}"; then
success "Preprocessing for '${profile}' completed."
else
err "Preprocessing for '${profile}' FAILED. Check logs for details."
if ! ask_confirm "Continue with other profiles?"; then
err "Aborting installation."
exit 1
fi
err "Preprocessing for '${profile}' FAILED."; if ! ask_confirm "Continue?"; then err "Aborting."; exit 1; fi
fi
docker compose -f "${COMPOSE_FILE}" rm -fsv "${service_name}" >/dev/null 2>&1 || true
done
else
info "All profile data already exists, skipping preprocessing."
fi
info "Starting all services for instance '${map_name}'..."
docker compose -f "${COMPOSE_FILE}" up -d --remove-orphans
success "Installation for '${map_name}' completed!"
print_summary
info "Starting all services for instance '${map_name}'..."; docker compose -f "${COMPOSE_FILE}" up --build -d --remove-orphans
success "Installation for '${map_name}' completed!"; print_summary
}
run_update() {
info "Starting update for instance '${map_name}', component '${sub_command}'"
if [ ! -f "${COMPOSE_FILE}" ]; then
err "Instance '${map_name}' not found."
exit 1
if [ ! -f "${COMPOSE_FILE}" ]; then err "Instance '${map_name}' not found."; exit 1; fi
local map_instance_dir="${work_dir}/${map_name}/dataset"
MAP_PATH=$(find "${map_instance_dir}" -name "*.osm.pbf" -print -quit)
if [[ "${sub_command}" != "backend" && "${sub_command}" != "frontend" && -z "${MAP_PATH}" ]]; then
err "Could not find existing map file for instance '${map_name}'."; exit 1;
fi
case "${sub_command}" in
backend | frontend | all)
info "Pulling latest images..."
docker pull "${DEFAULT_BACKEND_REGISTRY}:${DEFAULT_BACKEND_VERSION}"
if [[ "${sub_command}" != "backend" ]]; then
docker pull "${DEFAULT_FRONTEND_REGISTRY}:${DEFAULT_FRONTEND_VERSION}"
fi
info "Recreating services..."
docker compose -f "${COMPOSE_FILE}" up -d --remove-orphans
;;
map | profile)
if [[ "${sub_command}" == "map" ]]; then
download_map
fi
generate_profiles
info "Re-running preprocessing..."
for profile in "${PROFILE_ARR[@]}"; do
local pdata_dir="${work_dir}/${map_name}/${profile}-data"
info "Preparing map file for profile '${profile}'..."
cp -vf "${MAP_PATH}" "${pdata_dir}/map.osm.pbf"
local service_name="osrm-preprocess-${map_name}-${profile}"
docker compose -f "${COMPOSE_FILE}" up --build --exit-code-from "${service_name}" "${service_name}" || err "Preprocessing failed for ${profile}"
docker compose -f "${COMPOSE_FILE}" rm -fsv "${service_name}" >/dev/null 2>&1 || true
done
info "Restarting services..."
docker compose -f "${COMPOSE_FILE}" up -d --remove-orphans
;;
*)
err "Invalid update component."
exit 1
;;
backend|frontend)
info "Pulling latest base image for ${sub_command}...";
if [[ "${sub_command}" == "backend" ]]; then docker pull "${DEFAULT_BACKEND_REGISTRY}:${DEFAULT_BACKEND_VERSION}"; else docker pull "${DEFAULT_FRONTEND_REGISTRY}:${DEFAULT_FRONTEND_VERSION}"; fi
info "Rebuilding and recreating services..."; docker compose -f "${COMPOSE_FILE}" up --build -d --remove-orphans
;;
map) download_map; ;&
profile)
generate_profiles
if [[ "${no_frontend}" != "true" ]]; then generate_leaflet_options; generate_frontend_dockerfile; fi
generate_docker_compose
info "Re-running preprocessing for all specified profiles..."
for profile in "${PROFILE_ARR[@]}"; do
local pdata_dir="${work_dir}/${map_name}/${profile}-data"
info "Preparing map file for profile '${profile}'..."; cp -vf "${MAP_PATH}" "${pdata_dir}/map.osm.pbf"
local service_name="osrm-preprocess-${map_name}-${profile}"
docker compose -f "${COMPOSE_FILE}" up --build --exit-code-from "${service_name}" "${service_name}" || err "Preprocessing failed for ${profile}"
docker compose -f "${COMPOSE_FILE}" rm -fsv "${service_name}" >/dev/null 2>&1 || true
done
info "Restarting all services..."; docker compose -f "${COMPOSE_FILE}" up --build -d --remove-orphans
;;
*) err "Invalid update component. Use: backend, frontend, map, profile."; exit 1;;
esac
success "Update for '${map_name}' completed."
}
run_remove() {
info "Starting removal of OSRM instance: '${map_name}'"
if [ ! -f "${COMPOSE_FILE}" ]; then
warn "Instance '${map_name}' not found."
fi
if [ ! -f "${COMPOSE_FILE}" ]; then warn "Instance '${map_name}' not found."; fi
if ask_confirm "This will STOP and REMOVE all containers for instance '${map_name}'. Are you sure?"; then
if [ -f "${COMPOSE_FILE}" ]; then
docker compose -f "${COMPOSE_FILE}" down -v || warn "Could not stop containers."
rm -f "${COMPOSE_FILE}"
fi
success "All containers for '${map_name}' have been removed."
if [ -f "${COMPOSE_FILE}" ]; then docker compose -f "${COMPOSE_FILE}" down -v || warn "Could not stop containers."; fi
if [[ "${do_purge}" == "true" ]]; then
local instance_dir="${work_dir}/${map_name}"
if ask_confirm "PURGE ENABLED. This will DELETE '${instance_dir}'. IRREVERSIBLE. Proceed?"; then
rm -rf "${instance_dir}"
success "Instance data for '${map_name}' has been purged."
rm -rf "${instance_dir}"; rm -f "${COMPOSE_FILE}"; success "Instance data for '${map_name}' has been purged."
fi
fi
else
info "Removal aborted by user."
fi
else info "Removal aborted by user."; fi
}
print_summary() {
echo "--- Instance '${map_name}' Summary ---"
echo "Compose File: ${COMPOSE_FILE}"
echo "Map Source: ${MAP_PATH}"
echo "Profiles: ${profiles_csv}"
echo
echo "ACCESS POINTS (Example):"
local idx=0
echo "--- Instance '${map_name}' Summary ---"; echo "Profiles: ${profiles_csv}"
echo "ACCESS POINTS:"; local idx=0
for profile in "${PROFILE_ARR[@]}"; do
idx=$((idx + 1))
local host_port=$((backend_port + idx - 1))
echo " - Backend (${profile}): http://localhost:${host_port}${backend_path}/${api_version}/${profile}"
echo " (NGPM Target: osrm-routed-${map_name}-${profile}:5000)"
idx=$((idx + 1)); local host_port=$((backend_port + idx - 1))
echo " - Backend (${profile}): http://localhost:${host_port}"; echo " (NGPM Target: osrm-routed-${map_name}-${profile}:5000)"
done
if [ "${no_frontend}" != true ]; then
echo " - Frontend UI: http://localhost:${frontend_port}"
echo " (NGPM Target: osrm-frontend-${map_name}:9966)"
echo " - Frontend UI: http://localhost:${frontend_port}"; echo " (NGPM Target: osrm-frontend-${map_name}:9966)"
fi
echo "--------------------------"
}
main() {
parse_args "$@"
prereqs_check
setup_selinux_flag
info "Starting script execution."
info "Command: ${command_name}, Map Instance: ${map_name}"
parse_args "$@"; prereqs_check; setup_selinux_flag
info "Starting script execution."; info "Command: ${command_name}, Map Instance: ${map_name}"
case "${command_name}" in
install) run_install ;;
update) run_update ;;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment