From 08e8a6b228d4a433e0db364d9093d29f4d60b6ec Mon Sep 17 00:00:00 2001 From: "renato.ramos" Date: Wed, 25 Mar 2026 19:24:35 +0000 Subject: [PATCH] #main - adicionando arquivo 'install.sh' --- install.sh | 465 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 465 insertions(+) create mode 100644 install.sh diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..bc2b164 --- /dev/null +++ b/install.sh @@ -0,0 +1,465 @@ +#!/bin/bash + +# ============================================================== +# πŸš€ Instalador - AttendanceSystem +# Uso: +# bash <(curl -fsSL \ +# -H "Authorization: Bearer " \ +# "https://api.bitbucket.org/2.0/repositories/seventh-ltda/seventh.p7.attendance-system.install/src/main/install.sh") +# ============================================================== + +# ── Redireciona stdin para o terminal quando rodado via curl | bash ── +if [ -t 0 ]; then + : +else + exec < /dev/tty +fi + +set -e + +# ─── Cores ──────────────────────────────────────────────────── +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +BOLD='\033[1m' +DIM='\033[2m' +NC='\033[0m' + +# ─── RepositΓ³rio Git ────────────────────────────────────────── +INSTALL_DIR="attendancesystem" +BRANCH="${BRANCH:-main}" +ENV_FILE="" +GIT_REPO="https://x-token-auth:ATCTT3xFfGN0CpBIXNIZPOMuAl8dtHYHGmZEN1x3JnFCH-k-CZ8ZUogQB4Y74zMnKQIkEFMgeWqJnKPIG-E4mNoxZI9Kkr-KupfOyNrkI1K9FICcD07NgTEwLysmDdTU8qXfcuXww2gw5y-gLoRxxEFGSIC71IOgPDy9Z3Gs8ac-PE2QNTykhMA=C0C6CFDA@bitbucket.org/seventh-ltda/seventh.p7.attendance-system.install.git" + +# ══════════════════════════════════════════════════════════════ +# UtilitΓ‘rios +# ══════════════════════════════════════════════════════════════ + +print_banner() { + clear + echo -e "${CYAN}" + echo " ╔══════════════════════════════════════════════╗" + echo " β•‘ πŸš€ AttendanceSystem Installer β•‘" + echo " β•‘ InstalaΓ§Γ£o Guiada β•‘" + echo " β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•" + echo -e "${NC}" +} + +print_step() { + echo -e "\n${BLUE}${BOLD}β–Ά $1${NC}" +} + +print_section() { + echo -e "\n${CYAN}${BOLD} ── $1 ──${NC}" +} + +print_ok() { echo -e " ${GREEN}βœ” $1${NC}"; } +print_warn() { echo -e " ${YELLOW}⚠ $1${NC}"; } +print_error() { echo -e " ${RED}βœ– $1${NC}"; } + +ensure_http() { + local val="$1" + if [[ "$val" != http://* && "$val" != https://* ]]; then + echo "http://$val" + else + echo "$val" + fi +} + +ask() { + # ask [default] + local varname="$1" + local prompt="$2" + local default="$3" + local value="" + + if [ -n "$default" ]; then + echo -ne " ${BOLD}${prompt}${NC} ${DIM}[${default}]${NC}: " + else + echo -ne " ${BOLD}${prompt}${NC}: " + fi + + read -r value + value="${value:-$default}" + + while [ -z "$value" ]; do + echo -ne " ${RED}ObrigatΓ³rio.${NC} ${BOLD}${prompt}${NC}: " + read -r value + done + + eval "$varname=\"$value\"" +} + +confirm() { + echo -ne " ${BOLD}$1${NC} ${CYAN}[s/N]${NC}: " + read -r resp + [[ "$resp" =~ ^[sS]$ ]] +} + +press_enter() { + echo -ne "\n ${DIM}Pressione ENTER para continuar...${NC}" + read -r +} + + +# ══════════════════════════════════════════════════════════════ +# Verificar dependΓͺncias +# ══════════════════════════════════════════════════════════════ + +check_deps() { + print_step "Verificando dependΓͺncias..." + local missing=() + + for cmd in docker git make curl; do + if command -v "$cmd" &>/dev/null; then + print_ok "$cmd encontrado" + else + print_error "$cmd nΓ£o encontrado" + missing+=("$cmd") + fi + done + + if docker compose version &>/dev/null 2>&1; then + print_ok "docker compose (plugin) encontrado" + elif command -v docker-compose &>/dev/null; then + print_warn "docker-compose v1 encontrado β€” recomendamos atualizar para v2" + else + print_error "docker compose nΓ£o encontrado" + missing+=("docker-compose") + fi + + if [ ${#missing[@]} -gt 0 ]; then + echo "" + print_error "DependΓͺncias faltando: ${missing[*]}" + echo -e " Instale-as e execute o instalador novamente." + exit 1 + fi + + print_ok "Todas as dependΓͺncias OK" +} + +# ══════════════════════════════════════════════════════════════ +# Clonar / atualizar repositΓ³rio +# ══════════════════════════════════════════════════════════════ + +clone_repo() { + print_step "Baixando arquivos do projeto..." + + if [ -d "$INSTALL_DIR" ]; then + print_warn "A pasta '${INSTALL_DIR}' jΓ‘ existe." + if confirm "Deseja atualizar os arquivos? (git pull)"; then + cd "$INSTALL_DIR" && git pull && cd .. + print_ok "Arquivos atualizados" + else + print_warn "Usando arquivos existentes sem atualizar." + fi + else + git clone --branch "$BRANCH" "$GIT_REPO" "$INSTALL_DIR" + print_ok "Arquivos baixados em: $(pwd)/${INSTALL_DIR}" + fi + + ENV_FILE="$INSTALL_DIR/.env.prod" +} + +# ══════════════════════════════════════════════════════════════ +# Carregar .env.prod existente (modo reediΓ§Γ£o) +# ══════════════════════════════════════════════════════════════ + +load_existing_env() { + if [ ! -f "$ENV_FILE" ]; then + return + fi + + print_warn "ConfiguraΓ§Γ£o anterior encontrada em ${ENV_FILE}" + + if confirm "Deseja apenas subir o ambiente sem reconfigurar?"; then + cd "$INSTALL_DIR" && make install && cd .. + echo "" + echo -e "${GREEN}${BOLD} βœ… Ambiente iniciado com sucesso!${NC}" + echo "" + exit 0 + fi + + echo "" + print_ok "Carregando valores anteriores como padrΓ£o..." + + # LΓͺ variΓ‘veis do .env.prod ignorando comentΓ‘rios e linhas vazias + while IFS='=' read -r key value; do + [[ "$key" =~ ^#.*$ || -z "$key" ]] && continue + key="${key// /}" + value="${value// /}" + eval "$key=\"$value\"" + done < <(grep -v '^#' "$ENV_FILE" | grep -v '^$') + + # ReconstrΓ³i SYSTEM_BASE_HOST e PORT a partir de SYSTEM_BASE_CONN se necessΓ‘rio + if [ -n "$SYSTEM_BASE_CONN" ] && [ -z "$SYSTEM_BASE_HOST" ]; then + SYSTEM_BASE_HOST="${SYSTEM_BASE_CONN%:*}" + SYSTEM_BASE_PORT="${SYSTEM_BASE_CONN##*:}" + fi +} + +# ══════════════════════════════════════════════════════════════ +# SeΓ§Γ΅es de coleta de configuraΓ§Γ£o +# ══════════════════════════════════════════════════════════════ + +collect_hosts() { + print_section "1. Hosts" + ask INTERNAL_HOST "IP interno desta mΓ‘quina (rede local)" "${INTERNAL_HOST:-192.168.10.2}" + local _ext_default="${EXTERNAL_HOST:-$INTERNAL_HOST}" + ask EXTERNAL_HOST "IP externo desta mΓ‘quina (acesso remoto)" "$_ext_default" + INTERNAL_HOST=$(ensure_http "$INTERNAL_HOST") + EXTERNAL_HOST=$(ensure_http "$EXTERNAL_HOST") +} + +collect_system_base() { + print_section "2. Sistema Base (legado integrado)" + ask SYSTEM_BASE_HOST "IP/hostname do sistema base" "${SYSTEM_BASE_HOST:-192.168.10.1}" + ask SYSTEM_BASE_PORT "Porta do sistema base" "${SYSTEM_BASE_PORT:-8080}" + SYSTEM_BASE_HOST=$(ensure_http "$SYSTEM_BASE_HOST") +} + +collect_internal_ports() { + print_section "3. Portas Internas (rede local)" + ask BACKEND_SUITE_API_INTERNAL_PORT "Backend Suite API" "${BACKEND_SUITE_API_INTERNAL_PORT:-10101}" + ask BACKEND_PEOPLE_API_INTERNAL_PORT "Backend People API" "${BACKEND_PEOPLE_API_INTERNAL_PORT:-10100}" + ask BACKEND_ATTENDANCESYSTEM_API_INTERNAL_PORT "Backend AttendanceSystem API" "${BACKEND_ATTENDANCESYSTEM_API_INTERNAL_PORT:-10102}" + ask BACKEND_ACCOUNT_API_INTERNAL_PORT "Backend Account API" "${BACKEND_ACCOUNT_API_INTERNAL_PORT:-10103}" + ask FRONTEND_SUITE_APP_INTERNAL_PORT "Frontend Suite" "${FRONTEND_SUITE_APP_INTERNAL_PORT:-4200}" + ask FRONTEND_PEOPLE_APP_INTERNAL_PORT "Frontend People" "${FRONTEND_PEOPLE_APP_INTERNAL_PORT:-4201}" + ask FRONTEND_ATTENDANCESYSTEM_APP_INTERNAL_PORT "Frontend AttendanceSystem" "${FRONTEND_ATTENDANCESYSTEM_APP_INTERNAL_PORT:-4202}" + ask FRONTEND_ACCOUNT_APP_INTERNAL_PORT "Frontend Account" "${FRONTEND_ACCOUNT_APP_INTERNAL_PORT:-4203}" +} + +collect_external_ports() { + print_section "4. Portas Externas (NAT/acesso remoto)" + echo -e " ${DIM}Pressione ENTER para usar a mesma porta interna.${NC}\n" + + ask BACKEND_SUITE_API_EXTERNAL_PORT "Backend Suite API" "${BACKEND_SUITE_API_EXTERNAL_PORT:-$BACKEND_SUITE_API_INTERNAL_PORT}" + ask BACKEND_PEOPLE_API_EXTERNAL_PORT "Backend People API" "${BACKEND_PEOPLE_API_EXTERNAL_PORT:-$BACKEND_PEOPLE_API_INTERNAL_PORT}" + ask BACKEND_ATTENDANCESYSTEM_API_EXTERNAL_PORT "Backend AttendanceSystem API" "${BACKEND_ATTENDANCESYSTEM_API_EXTERNAL_PORT:-$BACKEND_ATTENDANCESYSTEM_API_INTERNAL_PORT}" + ask BACKEND_ACCOUNT_API_EXTERNAL_PORT "Backend Account API" "${BACKEND_ACCOUNT_API_EXTERNAL_PORT:-$BACKEND_ACCOUNT_API_INTERNAL_PORT}" + ask FRONTEND_SUITE_APP_EXTERNAL_PORT "Frontend Suite" "${FRONTEND_SUITE_APP_EXTERNAL_PORT:-$FRONTEND_SUITE_APP_INTERNAL_PORT}" + ask FRONTEND_PEOPLE_APP_EXTERNAL_PORT "Frontend People" "${FRONTEND_PEOPLE_APP_EXTERNAL_PORT:-$FRONTEND_PEOPLE_APP_INTERNAL_PORT}" + ask FRONTEND_ATTENDANCESYSTEM_APP_EXTERNAL_PORT "Frontend AttendanceSystem" "${FRONTEND_ATTENDANCESYSTEM_APP_EXTERNAL_PORT:-$FRONTEND_ATTENDANCESYSTEM_APP_INTERNAL_PORT}" + ask FRONTEND_ACCOUNT_APP_EXTERNAL_PORT "Frontend Account" "${FRONTEND_ACCOUNT_APP_EXTERNAL_PORT:-$FRONTEND_ACCOUNT_APP_INTERNAL_PORT}" +} + +collect_database() { + print_section "5. Banco de Dados" + ask MONGO_PORT "MongoDB (porta interna)" "${MONGO_PORT:-27017}" +} + +# ══════════════════════════════════════════════════════════════ +# Wizard principal β€” coleta com navegaΓ§Γ£o +# ══════════════════════════════════════════════════════════════ + +collect_config() { + print_step "ConfiguraΓ§Γ£o do ambiente" + echo -e " ${DIM}Pressione ENTER para aceitar o valor padrΓ£o mostrado entre colchetes.${NC}" + + collect_hosts + collect_system_base + + # Portas externas iguais Γ s internas? + echo "" + if confirm "As portas externas sΓ£o DIFERENTES das internas? (NAT/redirecionamento)"; then + collect_internal_ports + collect_external_ports + else + collect_internal_ports + # Copia internas β†’ externas automaticamente + BACKEND_SUITE_API_EXTERNAL_PORT="$BACKEND_SUITE_API_INTERNAL_PORT" + BACKEND_PEOPLE_API_EXTERNAL_PORT="$BACKEND_PEOPLE_API_INTERNAL_PORT" + BACKEND_ATTENDANCESYSTEM_API_EXTERNAL_PORT="$BACKEND_ATTENDANCESYSTEM_API_INTERNAL_PORT" + BACKEND_ACCOUNT_API_EXTERNAL_PORT="$BACKEND_ACCOUNT_API_INTERNAL_PORT" + FRONTEND_SUITE_APP_EXTERNAL_PORT="$FRONTEND_SUITE_APP_INTERNAL_PORT" + FRONTEND_PEOPLE_APP_EXTERNAL_PORT="$FRONTEND_PEOPLE_APP_INTERNAL_PORT" + FRONTEND_ATTENDANCESYSTEM_APP_EXTERNAL_PORT="$FRONTEND_ATTENDANCESYSTEM_APP_INTERNAL_PORT" + FRONTEND_ACCOUNT_APP_EXTERNAL_PORT="$FRONTEND_ACCOUNT_APP_INTERNAL_PORT" + print_ok "Portas externas definidas iguais Γ s internas." + fi + + collect_database +} + +# ══════════════════════════════════════════════════════════════ +# Resumo com menu de ediΓ§Γ£o +# ══════════════════════════════════════════════════════════════ + +show_summary() { + while true; do + echo "" + echo -e "${CYAN}${BOLD} β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”" + echo -e " β”‚ Resumo da configuraΓ§Γ£o β”‚" + echo -e " β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜${NC}" + echo "" + echo -e " ${BOLD}[1] Hosts${NC}" + echo -e " Interno : ${BOLD}${INTERNAL_HOST}${NC}" + echo -e " Externo : ${BOLD}${EXTERNAL_HOST}${NC}" + echo "" + echo -e " ${BOLD}[2] Sistema Base${NC}" + echo -e " Host : ${BOLD}${SYSTEM_BASE_HOST}${NC}" + echo -e " Porta : ${BOLD}${SYSTEM_BASE_PORT}${NC}" + echo "" + echo -e " ${BOLD}[3] Portas Internas${NC}" + echo -e " Backend Suite/People/Attendance/Account : ${BOLD}${BACKEND_SUITE_API_INTERNAL_PORT}${NC} / ${BOLD}${BACKEND_PEOPLE_API_INTERNAL_PORT}${NC} / ${BOLD}${BACKEND_ATTENDANCESYSTEM_API_INTERNAL_PORT}${NC} / ${BOLD}${BACKEND_ACCOUNT_API_INTERNAL_PORT}${NC}" + echo -e " Frontend Suite/People/Attendance/Account : ${BOLD}${FRONTEND_SUITE_APP_INTERNAL_PORT}${NC} / ${BOLD}${FRONTEND_PEOPLE_APP_INTERNAL_PORT}${NC} / ${BOLD}${FRONTEND_ATTENDANCESYSTEM_APP_INTERNAL_PORT}${NC} / ${BOLD}${FRONTEND_ACCOUNT_APP_INTERNAL_PORT}${NC}" + echo "" + echo -e " ${BOLD}[4] Portas Externas${NC}" + echo -e " Backend Suite/People/Attendance/Account : ${BOLD}${BACKEND_SUITE_API_EXTERNAL_PORT}${NC} / ${BOLD}${BACKEND_PEOPLE_API_EXTERNAL_PORT}${NC} / ${BOLD}${BACKEND_ATTENDANCESYSTEM_API_EXTERNAL_PORT}${NC} / ${BOLD}${BACKEND_ACCOUNT_API_EXTERNAL_PORT}${NC}" + echo -e " Frontend Suite/People/Attendance/Account : ${BOLD}${FRONTEND_SUITE_APP_EXTERNAL_PORT}${NC} / ${BOLD}${FRONTEND_PEOPLE_APP_EXTERNAL_PORT}${NC} / ${BOLD}${FRONTEND_ATTENDANCESYSTEM_APP_EXTERNAL_PORT}${NC} / ${BOLD}${FRONTEND_ACCOUNT_APP_EXTERNAL_PORT}${NC}" + echo "" + echo -e " ${BOLD}[5] Banco de Dados${NC}" + echo -e " MongoDB : ${BOLD}${MONGO_PORT}${NC}" + echo "" + echo -e " ──────────────────────────────────────────────────────────────" + echo -e " ${GREEN}${BOLD}[C]${NC} Confirmar e continuar ${RED}${BOLD}[X]${NC} Cancelar instalaΓ§Γ£o" + echo -e " ──────────────────────────────────────────────────────────────" + echo "" + echo -ne " ${BOLD}Digite o nΓΊmero da seΓ§Γ£o para editar, C para confirmar ou X para cancelar${NC}: " + read -r choice + + case "${choice^^}" in + 1) collect_hosts ;; + 2) collect_system_base ;; + 3) collect_internal_ports ;; + 4) collect_external_ports ;; + 5) collect_database ;; + C) break ;; + X) + echo "" + print_warn "InstalaΓ§Γ£o cancelada." + exit 0 + ;; + *) + print_warn "OpΓ§Γ£o invΓ‘lida. Digite 1-5, C ou X." + ;; + esac + done +} + +# ══════════════════════════════════════════════════════════════ +# Gerar arquivos .env +# ══════════════════════════════════════════════════════════════ + +generate_envs() { + print_step "Gerando arquivos de configuraΓ§Γ£o..." + + local BASE_DIR="$INSTALL_DIR" + local SYSTEM_BASE_CONN="${SYSTEM_BASE_HOST}:${SYSTEM_BASE_PORT}" + local KEEPALIVE_BACKEND="${EXTERNAL_HOST}:${BACKEND_ATTENDANCESYSTEM_API_EXTERNAL_PORT}" + local KEEPALIVE_FRONTEND="${EXTERNAL_HOST}:${FRONTEND_ATTENDANCESYSTEM_APP_EXTERNAL_PORT}" + + cat > "$BASE_DIR/.env.prod" <