diff --git a/builtin/cli-minimal.bash b/builtin/cli-minimal.bash index 7a1a2b1..d5616d6 100755 --- a/builtin/cli-minimal.bash +++ b/builtin/cli-minimal.bash @@ -9,11 +9,11 @@ export C_ORANGE="\033[38;5;208m" export C_GOLD="\033[38;5;220m" export C_PURPLE="\033[38;5;5m" -export S_INFO="${C_BLUE}\u2691 [info] ${NO_FMT} " -export S_SUCCESS="${C_GREEN}\u2691 [success] ${NO_FMT}\u2713 " +export S_INFO="${C_BLUE}\u2691 [info]${NO_FMT} " +export S_SUCCESS="${C_GREEN}\u2691 [success]${NO_FMT}\u2713 " export S_DEBUG="${C_PURPLE}\u2691 [debug]${NO_FMT} " -export S_WARN="${C_ORANGE}\u2691 [warning] ${NO_FMT} " -export S_ERROR="${C_RED}\u2691 [error] ${NO_FMT}\u2715 " +export S_WARN="${C_ORANGE}\u2691 [warning]${NO_FMT} " +export S_ERROR="${C_RED}\u2691 [error]${NO_FMT}\u2715 " export U_ITEM="\u2192" @@ -52,4 +52,3 @@ cli.section() { __section.content "${@:4}" __section.footer } -cli.section "${@}" diff --git a/builtin/cli.bash b/builtin/cli.bash new file mode 100644 index 0000000..19aaaaf --- /dev/null +++ b/builtin/cli.bash @@ -0,0 +1,104 @@ +export F_BOLD="\e[1m" +export F_NONE="\e[0m" + +export C_NONE="\e[0m" +export C_RED="\e[38;5;9m" +export C_BLUE="\e[38;5;12m" +export C_GREEN="\e[38;5;2m" +export C_ORANGE="\e[38;5;208m" +export C_YELLOW="\e[38;5;220m" +export C_PURPLE="\e[38;5;5m" + +export S_DEBUG="${C_PURPLE}\u2691 [debug]${F_NONE} " +export S_CRIT="${C_RED}\u2691 [critical]${F_NONE} " +export S_ERROR="${C_RED}\u2691 [error]${F_NONE} " +export S_WARN="${C_ORANGE}\u2691 [warning]${F_NONE} " +export S_INFO="${C_BLUE}\u2691 [info]${F_NONE} " +export S_NOTICE="${C_BLUE}\u2691 [notice]${F_NONE} " +export S_SUCCESS="${C_GREEN}\u2691 [success]${F_NONE} " + +export U_ITEM="\u21e2" +export U_TICK="\u2713" +export U_FAIL="\u2715" + +export COLS="$(( $(tput cols) - 1 ))" +export EL=$(tput el) + + +cli.cursor_pos() { + local _xy + + echo -ne $"\E[6n" + read -rsdR _xy + _xy="${_xy#*[}" + export CURSOR_X=${_xy/*;} + export CURSOR_Y=${_xy/;*} + return 0 +} + +cli.status() { + printf "%0.s\n" + case "${1:-info}" in + debug) printf "\e[0F${S_DEBUG}${2:-%s}" "${@:3}${EL}" ;; + crit*) printf "\e[0F${S_CRIT}${2:-%s}" "${@:3}${EL}" ;; + error) printf "\e[0F${S_ERROR}${2:-%s}" "${@:3}${EL}" ;; + warn*) printf "\e[0F${S_WARN}${2:-%s}" "${@:3}${EL}" ;; + info*) printf "\e[0F${S_INFO}${2:-%s}" "${@:3}${EL}" ;; + noti*) printf "\e[0F${S_NOTICE}${2:-%s}" "${@:3}${EL}" ;; + succ*) printf "\e[0F${S_SUCCESS}${2:-%s}" "${@:3}${EL}" ;; + *) printf "\e[0F${S_INFO}${2:-%s}" "${@:3}${EL}" ;; + esac + return 0 +} + +cli.color() { + case "${1:-info}" in + red) printf "${C_RED}${2:-%s}${C_NONE}" "${@:3}${EL}" ;; + blue) printf "${C_BLUE}${2:-%s}${C_NONE}" "${@:3}${EL}" ;; + green) printf "${C_GREEN}${2:-%s}${C_NONE}" "${@:3}${EL}" ;; + orange) printf "${C_ORANGE}${2:-%s}${C_NONE}" "${@:3}${EL}" ;; + yellow) printf "${C_YELLOW}${2:-%s}${C_NONE}" "${@:3}${EL}" ;; + purple) printf "${C_PURPLE}${2:-%s}${C_NONE}" "${@:3}${EL}" ;; + *) printf "${C_NONE}${2:-%s}${C_NONE}" "${@:3}${EL}" ;; + esac + return 0 +} + +cli.bold() { + printf "${F_BOLD}${1:-%s}${F_NONE}" "${@:2}${EL}" + return 0 +} + +cli.section() { + __section.header() { + __section.title() { + printf $"${@:1:1}" \ + $(echo -ne ${F_BOLD}${C_BLUE}${@:2:1}${F_NONE}) \ + $(echo -ne ${C_ORANGE}${@:3}${F_NONE}) + } + __section.title.underline() { + for i in $(seq 1 ${COLS}); do \ + printf "%s" $(echo -ne "\u2581"); \ + done + } + __section.title "${@}" + __section.title.underline + } + __section.content() { + printf "%2s\n" + printf "%s" "${@}" | fold -sw ${COLS} + } + __section.footer() { + __section.footer.line() { + [ -z "${1:-}" ] && printf "%s\n" + for i in $(seq 1 ${COLS}); do \ + printf "%s" $(echo -ne "\u2504${F_NONE}"); \ + done && \ + [ -z "${1:-}" ] && printf "%2s\n" + } + __section.footer.line + } + __section.header "${@:1:3}" + __section.content "${@:4}" + __section.footer +} diff --git a/sig-installer-dev b/sig-installer-dev index e0bf911..0a05864 100755 --- a/sig-installer-dev +++ b/sig-installer-dev @@ -1,68 +1,12 @@ #!/bin/bash + set -euo pipefail - -self=$(: "${0/*\/}"; echo ${_%%.*sh}) -version=2506.1 - -: ${LANG:=C.UTF-8} - -# Read the configuration from all config files found -CONFPATH="/etc/${self}:/usr/local/etc/${self}:.config:./config:." -for _p in ${CONFPATH//:/\ }; do - test -f ${_p}/${self}.conf && \ - . ${_p}/${self}.conf -done - -function cli() { - cli.__init__() { - local blob="\ - ZXhwb3J0IE5PX0ZNVD0iXDAzM1swbSIKZXhwb3J0IEZfQk9MRD0iXDAzM1sxbSIKCmV4cG9ydCBD \ - X05PTkU9IlwwMzNbMG0iCmV4cG9ydCBDX1JFRD0iXDAzM1szODs1OzltIgpleHBvcnQgQ19CTFVF \ - PSJcMDMzWzM4OzU7MTJtIgpleHBvcnQgQ19HUkVFTj0iXDAzM1szODs1OzJtIgpleHBvcnQgQ19P \ - UkFOR0U9IlwwMzNbMzg7NTsyMDhtIgpleHBvcnQgQ19HT0xEPSJcMDMzWzM4OzU7MjIwbSIKZXhw \ - b3J0IENfUFVSUExFPSJcMDMzWzM4OzU7NW0iCgpleHBvcnQgU19JTkZPPSIke0NfQkxVRX1cdTI2 \ - OTEgW2luZm9dICR7Tk9fRk1UfSAiCmV4cG9ydCBTX1NVQ0NFU1M9IiR7Q19HUkVFTn1cdTI2OTEg \ - W3N1Y2Nlc3NdICR7Tk9fRk1UfVx1MjcxMyAiCmV4cG9ydCBTX0RFQlVHPSIke0NfUFVSUExFfVx1 \ - MjY5MSBbZGVidWddJHtOT19GTVR9ICIKZXhwb3J0IFNfV0FSTj0iJHtDX09SQU5HRX1cdTI2OTEg \ - W3dhcm5pbmddICR7Tk9fRk1UfSAiCmV4cG9ydCBTX0VSUk9SPSIke0NfUkVEfVx1MjY5MSBbZXJy \ - b3JdICR7Tk9fRk1UfVx1MjcxNSAiCgpleHBvcnQgVV9JVEVNPSJcdTIxOTIiCgpleHBvcnQgQ09M \ - Uz0iJCgoICQodHB1dCBjb2xzKSAtIDEgKSkiCgpjbGkuc2VjdGlvbigpIHsKICBfX3NlY3Rpb24u \ - aGVhZGVyKCkgewogICAgX19zZWN0aW9uLnRpdGxlKCkgewogICAgICBwcmludGYgJCIke0A6MTox \ - fSIgXAogICAgICAgICQoZWNobyAtbmUgJHtGX0JPTER9JHtDX0JMVUV9JHtAOjI6MX0ke05PX0ZN \ - VH0pIFwKICAgICAgICAkKGVjaG8gLW5lICR7Q19PUkFOR0V9JHtAOjN9JHtOT19GTVR9KQogICAg \ - ICB9CiAgICBfX3NlY3Rpb24udGl0bGUudW5kZXJsaW5lKCkgewogICAgICBmb3IgaSBpbiAkKHNl \ - cSAxICR7Q09MU30pOyBkbyBcCiAgICAgICAgcHJpbnRmICIlcyIgJChlY2hvIC1uZSAiXHUyNTgx \ - Iik7IFwKICAgICAgZG9uZQogICAgfQogICAgX19zZWN0aW9uLnRpdGxlICIke0B9IgogICAgX19z \ - ZWN0aW9uLnRpdGxlLnVuZGVybGluZQogIH0KICBfX3NlY3Rpb24uY29udGVudCgpIHsKICAgIHBy \ - aW50ZiAiJTJzXG4iCiAgICBwcmludGYgIiVzIiAiJHtAfSIgfCBmb2xkIC1zdyAke0NPTFN9CiAg \ - fQogIF9fc2VjdGlvbi5mb290ZXIoKSB7CiAgICBfX3NlY3Rpb24uZm9vdGVyLmxpbmUoKSB7CiAg \ - ICAgIFsgLXogIiR7MTotfSIgXSAmJiBwcmludGYgIiVzXG4iCiAgICAgIGZvciBpIGluICQoc2Vx \ - IDEgJHtDT0xTfSk7IGRvIFwKICAgICAgICAgIHByaW50ZiAiJXMiICQoZWNobyAtbmUgIlx1MjUw \ - NCR7Tk9fRk1UfSIpOyBcCiAgICAgIGRvbmUgJiYgXAogICAgICBbIC16ICIkezE6LX0iIF0gJiYg \ - cHJpbnRmICIlMnNcbiIKICAgIH0KICAgIF9fc2VjdGlvbi5mb290ZXIubGluZQogIH0KICBfX3Nl \ - Y3Rpb24uaGVhZGVyICIke0A6MTozfSIKICBfX3NlY3Rpb24uY29udGVudCAiJHtAOjR9IgogIF9f \ - c2VjdGlvbi5mb290ZXIKfQpjbGkuc2VjdGlvbiAiJHtAfSIK \ - " - envfile=$(mktemp /tmp/sig-installer.env.XXXXXX) - echo $blob|base64 -di|grep -vE '^cli.*@' > ${envfile} - test -r ${envfile} && source ${envfile} - rm -f ${envfile} - } - cli.__init__ - clear -} +self=$(basename ${0}) +self=${self/.*bash} +version=2506.4 # == Funções Gerais ============================================================================== # -function self.check_sudo { - # Check if user has sudo access - if ! [[ (0$(id -u) -eq 0 || "$(groups)" =~ "sudo") ]]; then - echo -ne "${S_ERROR}" $"Este programa deve ser executado com 'sudo'.\n" - echo -ne "\\033[13G" $"Tente usar: ${C_BLUE}sudo ${0}${C_NONE}" - return 1 - fi -} - function self.check_essential { # We need at least some programs installed local _essential=" \ @@ -76,59 +20,33 @@ function self.check_essential { locales:locale-gen \ openssh-server:sshd \ sudo:sudo \ + unzip:unzip \ tzdata:tzconfig \ " - not_found= + local _not_found= for _prog in ${_essential}; do - if [[ -z "$(which ${_prog/*:} 2>/dev/null)" ]]; then - not_found+=" ${_prog}" + if [[ -z "$(which ${_prog/*:})" ]]; then + _not_found+=" ${_prog}" fi done - if [[ ! -z "$not_found" ]]; then - echo -ne "${S_ERROR}Os seguintes pacotes/programas são necessários para o instalador:\n\n" - for _prog in ${not_found}; do - echo " - ${_prog/*:} [${_prog/:*}]" - done; - [[ 0${#not_found} -gt 0 ]] \ - && cmd="apt-get -qq update; apt-get -qq -y install " - printf "%2s\n" - for _prog in ${not_found}; do - echo " - Instalando ${_prog/:*}:" - cmd+="${_prog/:*} " - done; - echo $cmd - return 2 + if [[ ! -z "$_not_found" ]]; then + clear + echo -e "Os seguintes pacotes/programas são necessários para o instalador:\n" + _pkgs= + for _prog in ${_not_found}; do + echo " - ${_prog/:*}: ${_prog/*:}" + _pkgs+="${_prog/:*} " + done + read -p \ + $"Aperte ENTER para instalar os pacotes agora [CTRL+C para cancelar]: " + apt-get update + apt-get install -yq ${_pkgs} fi } +self.check_essential -eval cli -cli.section "%s [VERSÃO: %s]\n" \ - ${self^^} \ - ${version} \ - "$(self.check_sudo)" \ - "$(self.check_essential)" - -function self.decode() { - local _passphrase="Sig%$ºluc03s" - - tail -n +$(( \ - ${LINENO} + \ - $(\ - : "$( \ - grep -anP "^exit 0" ${0})"; \ - echo $(( ${_%%:*} - ${LINENO} + 2)) \ - ) \ - )) ${0} | base64 -d \ - | bsdtar \ - --passphrase ${_passphrase} \ - -xOf - - - return ${?} -} - -exit 1 # -- Import functions from local or remote scripts function import { case ${1} in @@ -146,13 +64,25 @@ function import { } # -- YAML Parser +: parsers.yaml file.yml key function parsers.yaml { - local _index=$(echo "['${2}']" | sed "s/\./\'\]\[\'/g") + local \ + out= err= + + parse() { + python3 -c "import yaml; \ + f=yaml.safe_load(open('${1}'))['${2//\./\'][\'}']; \ + print('\n'.join(str(i) for i in f) if type(f)==list else f); \ + " + } + + if res=$(parse $@ 2>&1); then + out=${res} && echo ${out} + else + err=$(: "${res//*\}"; echo "${_//:\ /: \[}]") + ${ui}.status error "%s ${U_SUBITEM} %s " "${1##*\/} ${err}" $"NotFound" + fi - python3 -c "import yaml; \ - f=yaml.safe_load(open('${1}'))${_index}; \ - print('\n'.join(str(i) for i in f) if type(f)==list else f); \ - " } # == UI =======================================================================+================= # @@ -161,7 +91,9 @@ ui=${ui:-cli} dbtool=https://raw.githubusercontent.com/infra7ti/dbtool/refs/heads/main import ${dbtool}/lib/ui/${ui}.bash -_() { echo $"${1}"; } +function cli.clear { + clear +} function cli.status { ${ui}.${@:1:1} && ${ui}.print "${@:2}" @@ -200,6 +132,14 @@ function system.check_os { return 0 } +function system.check_sudo { + # Check if user has sudo access + if ! [[ (0$(id -u) -eq 0 || "$(groups)" =~ "sudo") ]]; then + ${ui}.status error $"Por favor use um usuário com privilégios de sudo" + sleep 10 && exit 1 + fi +} + function system.setlocale { ${ui}.status info $"Configurando locales do sistema ..." for _locale in C en_US pt_BR; do @@ -372,14 +312,16 @@ function system.install_postgres { system.install_pkgs ${POSTRES_PACKAGES} - pg_conftool ${_pg_version} main set listen.address '*' - pg_conftool ${_pg_version} main set log.timezone 'America/Sao_Paulo' + pg_conftool ${_pg_version} main set listen_addresses '*' + pg_conftool ${_pg_version} main set log_timezone 'America/Sao_Paulo' pg_conftool ${_pg_version} main set shared_preload_libraries ${_pg_shared_preload} local _pg_hba_file="/etc/postgresql/${_pg_version}/main/pg_hba.conf" sudo cat <<-EOF | sed 's/^\s*\(.*\)/\1/g' > ${_pg_hba_file} + # Local Administrative User + local all postgres peer # "local" is for Unix domain socket connections only - local all all peer + local all all scram-sha-256 # IPv4 local connections: host all all 127.0.0.1/32 scram-sha-256 host all all 0.0.0.0/0 scram-sha-256 @@ -388,7 +330,7 @@ function system.install_postgres { host all all ::/0 scram-sha-256 # Allow replication connections from localhost, by a user with the # replication privilege. - #local replication all peer + #local replication all scram-sha-256 #host replication all 127.0.0.1/32 scram-sha-256 #host replication all ::1/128 scram-sha-256 EOF @@ -404,6 +346,7 @@ EOF ${ui}.status tab "${line}"; \ done ${ui}.color none + echo } function system.install_pyenv { @@ -425,7 +368,9 @@ function system.install_pyenv { export PYENV_ROOT="${_pyenv_root:-/usr/local/share/pyenv}" useradd -M -d ${PYENV_ROOT} -s /bin/bash -r -U pyenv >/dev/null 2>&1 || : - [[ -d "${PYENV_ROOT}" ]] && return 0 + [[ -d "${PYENV_ROOT}" ]] && \ + ${ui}.status info $"PyEnv já está configurado!\n" && \ + return 0 system.install_pkgs ${PYENV_PACKAGES} #rm -rf ${PYENV_ROOT} ${ui}.status info $"Instalando PyENV [%s] ..." ${PYENV_ROOT} @@ -477,9 +422,19 @@ EOF } -# == Produtos SIG =======================================================================+======= # +# == Installer =================================================================================== # -function download { +function installer.configure { + local _passphrase + + ${ui}.prompt $"Frase secreta para acesso aos downloads: " _passphrase + PRIVKEY_PASSPHRASE="${_passphrase}" + + ! [[ "X" == "${PRIVKEY_PASSPHRASE}X" ]] && \ + ${ui}.status info $"Frase secreta armazenada com sucesso." ${_passphrase} +} + +function installer.download { local _src="${1:-}" local _dst="${2:-${CACHEDIR}/$(basename ${1})}" local _quiet=${3:-} @@ -488,319 +443,666 @@ function download { local _repo_user="dl" local _token=$(mktemp /tmp/${self}.dl.XXXXXX) + local _token_pass=${PRIVKEY_PASSPHRASE} local _seek=$(($(grep -anE "^exit 0" ${0} | cut -d: -f1) - ${LINENO} + 1)) local _message="$(tail -n +$(( ${LINENO} + ${_seek} )) ${0})" [[ -z "${_quiet}" ]] && ${ui}.status info $"Fazendo download [${_src}]" (echo ${_message} | base64 -d \ - | bsdtar --passphrase ${token_pass} -C $(dirname ${_token}) -xOf - > ${_token} \ + | bsdtar --passphrase ${_token_pass} -C $(dirname ${_token}) -xOf - > ${_token} \ && chmod 0400 ${_token} \ && scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \ -qi ${_token} "${_repo_user}@${_repo_home}/${_src}" "${_dst}" \ && color=green || color=red; \ ${ui}.color ${color}; \ - echo "${_src}" | sed "s/^\(.*\)/\ \ $(${ui}.item '')\1/g"; \ + ! [[ "${_quiet}" == "silent" ]] \ + && echo "${_src}" | sed "s/^\(.*\)/\ \ $(${ui}.item '')\1/g"; \ ${ui}.color none; \ ) rm -f ${_token} } -function menu.produtos { - clear - ${ui}.init "%s [VERSÃO: %s] - CONFIGURAÇÃO DOS PRODUTOS\n" ${self^^} ${version} - #token_pass=$(${ui}.prompt "Senha de acesso aos downloads: " -s) +function installer.download_metadata { + local \ + _metadata_uri="installer/config/sig-installer" \ + _metadata_name="${1:-products}" - token_pass="Sig%$ºluc03s" - ${ui}.status info $"Atualizando lista de produtos\n" + installer.download \ + "${_metadata_uri}/${_metadata_name}.yml" \ + "${metadata_cache}/${_metadata_name}.yml" \ + silent +} - _repo='installer' - download "${_repo}/config/produtos.yml" "${CACHEDIR}/produtos.yml" >/dev/null 2>&1 - download "${_repo}/config/versoes.yml" "${CACHEDIR}/versoes.yml" >/dev/null 2>&1 +function installer.load_products { + local \ + _product_metadata="${metadata_cache}/products.yml" \ + _version_metadata="${metadata_cache}/versions.yml" \ + _id _prod _products - _produtos=$( \ - parsers.yaml ${CACHEDIR}/produtos.yml "produtos" \ - | sed "s/'/\"/g" \ - | jq "to_entries[] | select(.value.restricted|not) | .key" \ - | sed 's/"//g' | sort - ) + _products=$( \ + parsers.yaml "${_product_metadata}" "products" \ + | sed "s/'/\"/g" \ + | jq "to_entries[] | select(.value.restricted|not) | .key" \ + | sed 's/"//g' | sort + ) + + echo "${_products}" +} + +function installer.product.menu { + metadata_cache="${CACHEDIR}" + + local \ + _product_metadata="${metadata_cache}/products.yml" \ + _version_metadata="${metadata_cache}/versions.yml" \ + _products _prod_variant _prod_name _prod_color \ + _prod_version _id _prod + + ${ui}.clear + ${ui}.init "%s [VERSÃO: %s] - CONFIGURAÇÃO DE PRODUTOS\n" ${self^^} ${version} + + PRIVKEY_PASSPHRASE=Sig%$ºluc03s + while [[ -z "${PRIVKEY_PASSPHRASE}" ]]; do + installer.configure + done + + ${ui}.status info $"Atualizando metadados de produtos... \n" + installer.download_metadata products + installer.download_metadata versions + installer.download_metadata repos + _products="$(installer.load_products)" + + #${ui}.title $"Produtos:"; + ${ui}.title $"Instalar/Atualizar Produtos:" - ${ui}.title $"Instalar/Configurar Produtos:"; _id=1 - declare -A produtos - for _pd in ${_produtos}; do - produtos["${_id}"]="${_pd}" - _pdpy=$(parsers.yaml ${CACHEDIR}/produtos.yml "produtos.${_pd}.python") - _name=$(parsers.yaml ${CACHEDIR}/produtos.yml "produtos.${_pd}.name") - _pdpv=$(parsers.yaml ${CACHEDIR}/versoes.yml "produtos.python${_pdpy/.*}.${_pd}") + declare -A products + for _prod in ${_products}; do + products[${_id}]="${_prod}" + _prod_variant=$(parsers.yaml "${_product_metadata}" "products.${_prod}.variant") + _prod_name=$(parsers.yaml "${_product_metadata}" "products.${_prod}.name") + _prod_color=$(parsers.yaml "${_product_metadata}" "products.${_prod}.color") + _prod_version=$(parsers.yaml "${_version_metadata}" "products.${_prod}-${_prod_variant}") + ${ui}.status tab "$( \ ${ui}.color blue)${_id}.$(${ui}.color none) $( \ - ${ui}.print "${_name} ["VERSÃO:" ${_pdpv#*/}]" \ + ${ui}.print \ + "%s (%s) [%s: %s]" \ + "${F_BOLD}Sig${NO_FMT}$(${ui}.color ${_prod_color})${_prod_name#Sig*}${NO_FMT}" \ + ${_prod_variant^} \ + $"VERSÃO" $(${ui}.color orange)${_prod_version#*/}$(${ui}.color none) \ )" let _id=_id+1 done; echo - ${ui}.status tab "$( \ - ${ui}.color blue)${_id}.$(${ui}.color none) $( \ - ${ui}.print $"Limpar downloads e terminar" \ - )" - ${ui}.line - ${ui}.prompt $"Selecione o produto: " id + ${ui}.subtitle $"Configurações:" - # Sair do instalador - [ 0${id} -eq 0${_id} ] && rm -rf ${CACHEDIR} && exit 0 - export PRODUTO=${produtos[$id]} + ${ui}.status tab "$( \ + ${ui}.color blue)C.$(${ui}.color none) $( \ + ${ui}.print $"Configuração do Instalador" \ + )" + + ${ui}.status tab "$( \ + ${ui}.color blue)Q.$(${ui}.color none) $( \ + ${ui}.print $"Limpar downloads e Sair" \ + )" + + ${ui}.line + ${ui}.prompt $"Selecione a opção: " id + + case ${id} in + Q|q) rm -rf ${CACHEDIR} && exit 0 ;; + C|c) installer.configure ;; + *) true ;; + esac + + [[ ${products[${id}]+x} ]] || return 0 + PRODUCT=${products[$id]} } -function produto.download { - _repo='software' +# == Products ==================================================================================== # - _pdpy=$(parsers.yaml ${CACHEDIR}/produtos.yml "produtos.${PRODUTO}.python") - _libs=$(parsers.yaml ${CACHEDIR}/produtos.yml "produtos.${PRODUTO}.download") - _pdpv=$(parsers.yaml ${CACHEDIR}/versoes.yml "produtos.python${_pdpy/.*}.${PRODUTO}") +function product.get_requires { + import /etc/os-release + local _os_id=${ID} - mkdir -p ${CACHEDIR}/${PRODUTO} - ${ui}.status info $"Fazendo download dos arquivos ..." - for _lib in ${_libs}; do - _lbpv=$(parsers.yaml ${CACHEDIR}/versoes.yml libs.python${_pdpy/.*}.${_lib}) - download "${_repo}/libs/${_lib}/${_lbpv/\/*}/${_lib}-${_lbpv#*/}.tar.gz" \ - "${CACHEDIR}/${PRODUTO}/${_lib}-${_lbpv#*/}.tar.gz" --quiet + _get_product_requires() { + local \ + _prod_metadata="${CACHEDIR}/products.yml" \ + _version_metadata="${CACHEDIR}/versions.yml" \ + _prod_name _prod_variant _prod_color _prod_paths \ + _prod_requires _prod_buildreq _prod_config _prod_version \ + _rq _br _pkg _repo + + ! [[ "X" == "${PRODUCT:-${1}}X" ]] || return 1 + + _prod_requires=$(parsers.yaml ${_prod_metadata} "products.${PRODUCT}.requires") + _prod_buildreq=$(parsers.yaml ${_prod_metadata} "products.${PRODUCT}.buildrequires") + + # Not used here: + #_prod_name=$(parsers.yaml ${_prod_metadata} "products.${PRODUCT}.name") + #_prod_variant=$(parsers.yaml ${_prod_metadata} "products.${PRODUCT}.variant") + #_prod_color=$(parsers.yaml ${_prod_metadata} "products.${PRODUCT}.color") + #_prod_paths=$(parsers.yaml ${_prod_metadata} "products.${PRODUCT}.paths") + #_prod_config=$(parsers.yaml ${_prod_metadata} "products.${PRODUCT}.config") + #_prod_version=$(parsers.yaml ${_version_metadata} "products.${PRODUCT}-${_prod_variant}") + + for _rq in ${_prod_requires}; do + [[ "${_rq}" =~ "${_os_id}" ]] && : "${_rq#*/}"; REQUIRES+="${_%~*} " + done + + for _br in ${_prod_buildreq}; do + [[ "${_br}" =~ "${_os_id}" ]] && : "${_br#*/}"; BUILD_REQUIRES+="${_%~*} " + done + + for _pkg in ${_prod_requires} ${_prod_buildreq}; do + : "${_pkg%"${_pkg##*\/}"}"; _repo=${_%\/*} + case ${_repo} in + ""|default) continue ;; + local) echo "${_pkg}" >> ${CACHEDIR}/${PRODUCT}.local.build ;; + sig) DOWNLOADS+="${_pkg} " ;; + *) ! [[ "${REPOS}" =~ "${_repo}" ]] && REPOS+="${_repo} " + esac + done + } + + _get_product_repos_requires() { + local \ + repo_metadata="${CACHEDIR}/repos.yml" \ + _repo _repo_summary _repo_type _repo_dists \ + _repo_requires _repo_buildreq _repo_script \ + _rq _br + + for _repo in ${REPOS}; do + _repo_requires=$(parsers.yaml ${repo_metadata} "repos.${_repo}.requires") + _repo_buildreq=$(parsers.yaml ${repo_metadata} "repos.${_repo}.buildrequires") + + # Not used here: + #_repo_summary=$(parsers.yaml ${repo_metadata} "repos.${_repo}.summary") + #_repo_type=$(parsers.yaml ${repo_metadata} "repos.${_repo}.type") + #_repo_dists=$(parsers.yaml ${repo_metadata} "repos.${_repo}.dists") + #_repo_script=$(parsers.yaml ${repo_metadata} "repos.${_repo}.run") + done + + for _rq in ${_repo_requires:-}; do + [[ "${_rq}" =~ "${_os_id}" ]] && : "${_rq#*/}"; REQUIRES+="${_%~*} " + done + + for _br in ${_repo_buildreq:-}; do + [[ "${_br}" =~ "${_os_id}" ]] && : "${_br#*/}"; BUILD_REQUIRES+="${_%~*} " + done + } + + _get_product_requires + _get_product_repos_requires + + #DEBUG=1 + #${ui}.status info "%s: %s\n" $"Requires" "${REQUIRES}" + #${ui}.status info "%s: %s\n" $"BuildRequires" "${BUILD_REQUIRES}" + #${ui}.status info "%s: %s\n" $"Repos" "${REPOS}" + #[[ ${DEBUG:-0} -gt 0 ]] && sleep 10 + #return 0 +} + +function product.setup_repos { + local \ + _repo _repo_name _repo_summary \ + _repo_script + + _product.repo.get_property() { + local \ + __repo_metadata="${CACHEDIR}/repos.yml" \ + __repo="${1:-}" \ + __repo_property="${2:-}" + + echo "$(parsers.yaml ${__repo_metadata} "repos.${__repo}.${__repo_property}")" + } + + for _repo in ${REPOS}; do + _repo_name=${_repo} + _repo_summary="$(_product.repo.get_property ${_repo} summary)" + _repo_type=$(_product.repo.get_property ${_repo} type) + + ${ui}.status info $"Configurando Repositório [%s]" ${_repo_name} + ${ui}.status tab $"Sumário: ${_repo_summary}\n" + case ${_repo_type} in + local) true ;; + run) + _repo_script=$(_product.repo.get_property ${_repo} run) + ;; + deb) echo "Não implementado" ;; + rpm-md) echo "Não Implementado" ;; + *) true ;; + esac + eval $(echo "${_repo_script}") done - download "${_repo}/${PRODUTO}/${_pdpv/\/*}/${PRODUTO}-${_pdpv#*/}.tar.gz" \ - "${CACHEDIR}/${PRODUTO}/${PRODUTO}-${_pdpv#*/}.tar.gz" --quiet +} + +function product.get_property { + local \ + _prod_variant \ + _prod_verpath + + _get_property() { + metadata_cache="${CACHEDIR}" + + local \ + _product_metadata="${metadata_cache}/products.yml" \ + _version_metadata="${metadata_cache}/versions.yml" \ + _key=${PRODUCT}${1:-} + + echo $(parsers.yaml "${_product_metadata}" \ + "products.${_key}") + } + + _prod_variant=$(_get_property .variant) + + # Treat if product has variants: + # true: verpath field comes from yaml key - + # false: verpath field comes from yaml key + ! [[ "${PRODUCT}" == "${_prod_variant}" ]] \ + && _prod_verpath=$(_get_property -${_prod_variant}) \ + || _prod_verpath=$(_get_property) + + case "${1:-}" in + name) echo "$(_get_property .name)" ;; + version) echo "$(basename ${_prod_verpath})" ;; + variant) echo "$(_get_property .variant)" ;; + dowload_uri) continue ;; + cache_file) continue ;; + *) true ;; + esac + +} + +function product.download { + metadata_cache="${CACHEDIR}" + + local \ + _product_metadata="${metadata_cache}/products.yml" \ + _version_metadata="${metadata_cache}/versions.yml" \ + _prod_variant _prod_verpath _prod_download_uri \ + _prod_root="software" _prod_output_dir _prod_file _lib \ + _lib_root="software/libs" _lib_name _lib_variant _lib_verpath \ + _lib_path _lib_download_uri _lib_file _ext="tar.gz" + + [[ -z "${PRODUCT}" ]] && return 1 + + _prod_variant=$(parsers.yaml "${_product_metadata}" \ + "products.${PRODUCT}.variant") + + # Treat if product has variants: + # true: verpath field comes from yaml key - + # false: verpath field comes from yaml key + ! [[ "${PRODUCT}" == "${_prod_variant}" ]] \ + && _prod_verpath=$(parsers.yaml "${_version_metadata}" \ + "products.${PRODUCT}-${_prod_variant}") \ + || _prod_verpath=$(parsers.yaml "${_version_metadata}" \ + "products.${PRODUCT}") + + _get_download_uri() { + local _p=$(dirname "${3}") + + ! [[ "${_p}" == "." ]] && _p="${_p}/" || _p= + echo "${1}/${2}/${_p}${2}-${3/*\/}.${4:-tar.gz}" + } + + _get_output_file() { + echo "${metadata_cache}/${PRODUCT}/${1}-${2/*\/}.${3:-tar.gz}" + } + + #[[ "${@}" =~ '(ext=tar\.[bgxz]{2}\d*)' ]] \ + # && _ext="${BASH_REMATCH[1]}" + + _prod_download_uri="$(_get_download_uri ${_prod_root} \ + ${PRODUCT} ${_prod_verpath} ${_ext})" + _prod_output_file="$(_get_output_file ${PRODUCT} \ + ${_prod_verpath} ${_ext})" + + mkdir -p $(dirname ${_prod_output_file}) + ${ui}.status info $"Fazendo download dos arquivos ..." + installer.download \ + "${_prod_download_uri}" \ + "${_prod_output_file}" \ + --quiet + + for _lib in ${DOWNLOADS}; do + _lib_name=$(: "${_lib%:*}"; echo "${_#*\/}") + _lib_variant=$(: "${_lib#*/}"; echo "${_#*:}") + + # Treat if library has variants: + # true: verpath field comes from yaml key - + # false: verpath field comes from yaml key + ! [[ "${_lib_name}" == "${_lib_variant}" ]] \ + && _lib_verpath=$(parsers.yaml "${_version_metadata}" \ + "downloads.${_lib_name}-${_lib_variant}") \ + || _lib_verpath=$(parsers.yaml "${_version_metadata}" \ + "downloads.${_lib_name}") + + _lib_download_uri="$(_get_download_uri ${_lib_root} \ + ${_lib_name} ${_lib_verpath} ${_ext})" + _lib_output_file="$(_get_output_file ${_lib_name} \ + ${_lib_verpath} ${_ext})" + + installer.download \ + "${_lib_download_uri}" \ + "${_lib_output_file}" \ + --quiet + done + + exit 1 chmod g+rx,o+rx ${CACHEDIR} ${ui}.status info $"Download concluído." #${ui}.prompt $"Pressione uma tecla para continuar ... " } -function produto.install { +function product.install { + ${ui}.clear + ${ui}.init $"%s [VERSÃO: %s] - INSTALAÇÃO DO PRODUTO\n" ${self^^} ${version} + ${ui}.title "$(product.get_property name)" + mkdir -p /srv/sig - - - BUILD_PACKAGES=" \ - build-essential - libmysqlclient-dev - gcc - libbz2-dev - libcups2-dev - libevent-dev - libffi-dev - libfreetype6-dev - libfribidi-dev - libharfbuzz-dev - libjpeg8-dev - liblcms2-dev - libldap2-dev - liblzma-dev - libmysqlclient-dev - libncursesw5-dev - libopenjp2-7-dev - libpq-dev - libreadline-dev - libsasl2-dev - libsqlite3-dev - libssl-dev - libtiff5-dev - libwebp-dev - libxcb1-dev - libxml2-dev - libxmlsec1-dev - libxslt1-dev - llvm - make - ncurses-dev - pyqt5-dev - python3-pip - swig - tk-dev - zlib1g-dev - " + ln -snf /srv/sig /sig # -- Instalando pacotes necessários - system.install_pkgs ${BUILD_PACKAGES} + system.install_pkgs ${BUILD_REQUIRES} - _pdpy=$(parsers.yaml ${CACHEDIR}/produtos.yml "produtos.${PRODUTO}.python") - _name=$(parsers.yaml ${CACHEDIR}/produtos.yml "produtos.${PRODUTO}.name") - _libs=$(parsers.yaml ${CACHEDIR}/produtos.yml "produtos.${PRODUTO}.download") - _pdpv=$(parsers.yaml ${CACHEDIR}/versoes.yml "produtos.python${_pdpy/.*}.${PRODUTO}") - useradd -m -d /srv/sig/${PRODUTO} -s /bin/bash -G pyenv -r -U ${PRODUTO} 2>/dev/null || : - cat /etc/skel/.bashrc > /srv/sig/${PRODUTO}/.bashrc - echo -e "\n# Load Python ${_pdpy}\npyenv local ${_pdpy} >/dev/null 2>&1" >> /srv/sig/${PRODUTO}/.bashrc - echo ${_pdpy} > /srv/sig/${PRODUTO}/.python-version + + _pdpy=$(parsers.yaml ${CACHEDIR}/products.yml "products.${PRODUCT}.python") + _name=$(parsers.yaml ${CACHEDIR}/products.yml "products.${PRODUCT}.name") + _libs=$(parsers.yaml ${CACHEDIR}/products.yml "products.${PRODUCT}.download") + _pdpv=$(parsers.yaml ${CACHEDIR}/versions.yml "products.python${_pdpy/.*}.${PRODUCT}") + + useradd -m -d /srv/sig/${PRODUCT} -s /bin/bash -G pyenv -r -U ${PRODUCT} 2>/dev/null || : + cat /etc/skel/.bashrc > /srv/sig/${PRODUCT}/.bashrc + echo -e "\n# Load Python ${_pdpy}\npyenv local ${_pdpy} >/dev/null 2>&1" >> /srv/sig/${PRODUCT}/.bashrc + echo ${_pdpy} > /srv/sig/${PRODUCT}/.python-version ${ui}.status info $"Instalando produto [%s] ..." "${_name}" ${ui}.color gold - runuser -l ${PRODUTO} -- python -m pip install --upgrade --user pip - runuser -l ${PRODUTO} -- python -m pip install --upgrade --user setuptools + runuser -l ${PRODUCT} -- python -m pip install --upgrade --user pip + runuser -l ${PRODUCT} -- python -m pip install --upgrade --user setuptools for _lib in ${_libs}; do - [[ "${_lib}" == "stoqdrivers" ]] && continue - _lbpv=$(parsers.yaml ${CACHEDIR}/versoes.yml libs.python${_pdpy/.*}.${_lib}) - runuser -l ${PRODUTO} -- python -m pip install --user \ - "${CACHEDIR}/${PRODUTO}/${_lib}-${_lbpv#*/}.tar.gz" + _lbpv=$(parsers.yaml ${CACHEDIR}/versions.yml libs.python${_pdpy/.*}.${_lib}) + runuser -l ${PRODUCT} -- python -m pip install --user \ + "${CACHEDIR}/${PRODUCT}/${_lib}-${_lbpv#*/}.tar.gz" + if [[ "${_lib}" == "kiwi" ]]; then + _f=/srv/sig/${PRODUCT}/.local/lib/python2.7/site-packages/kiwi/__installed__.py + find $(dirname ${_f})/ -name *.pyc -delete + download "installer/config/${PRODUCT}/__installed__.py" "${_f}" \ + && chown -R ${PRODUCT}:${PRODUCT} "${_f}" \ + && chmod 644 ${_f} \ + && touch ${_f} + fi done - case "${PRODUTO}" in + case "${PRODUCT}" in sigerp) _date=$(date +%Y%m%d%H%M%S) - [[ -d "/srv/sig/${PRODUTO}/addons" ]] && \ + _pdpy=$(parsers.yaml ${CACHEDIR}/products.yml "products.${PRODUCT}.python") + + # Addons SigERP + [[ -d "/srv/sig/${PRODUCT}/addons" ]] && \ mv \ - /srv/sig/${PRODUTO}/addons \ - /srv/sig/${PRODUTO}/addons.${_date}.bak - mkdir -p /srv/sig/${PRODUTO}/{addons,config} - tar -C /srv/sig/${PRODUTO}/addons/ \ - -xzf ${CACHEDIR}/${PRODUTO}/${PRODUTO}-${_pdpv#*/}.tar.gz + /srv/sig/${PRODUCT}/addons \ + /srv/sig/${PRODUCT}/addons.${_date}.bak + mkdir -p /srv/sig/${PRODUCT}/{addons,config,logs,data-dir} /run/${PRODUCT} + tar -C /srv/sig/${PRODUCT}/addons/ \ + -xzf ${CACHEDIR}/${PRODUCT}/${PRODUCT}-${_pdpv#*/}.tar.gz + download "installer/config/${PRODUCT}/requirements.txt" \ + "/srv/sig/${PRODUCT}/addons/requirements.txt" + [[ -f "/srv/sig/${PRODUCT}/addons/requirements.txt" ]] && \ + runuser -l ${PRODUCT} -- \ + python -m pip install -r /srv/sig/${PRODUCT}/addons/requirements.txt --user + chown -R ${PRODUCT}: /srv/sig/${PRODUCT}/ /run/${PRODUCT} - download "installer/config/${PRODUTO}/requirements.txt" \ - "/srv/sig/${PRODUTO}/addons/requirements.txt" + # Runner and systemd units + download "installer/config/${PRODUCT}/sigerp-runner-pyenv-${_pdpy}.sh" \ + "/srv/sig/${PRODUCT}/sigerp-runner" \ + && chmod +x "/srv/sig/${PRODUCT}/sigerp-runner" \ + && ln -snf \ + "/srv/sig/${PRODUCT}/sigerp-runner" \ + "/usr/local/bin/sigerp-runner" + download "installer/config/${PRODUCT}/sigerp.service" \ + "/srv/sig/${PRODUCT}/sigerp.service" \ + && ln -snf \ + "/srv/sig/${PRODUCT}/sigerp.service" \ + "/etc/systemd/system/sigerp.service" \ + && ln -snf \ + "sigerp.service" \ + "/etc/systemd/system/openerp.service" + download "installer/config/${PRODUCT}/sigerp@.service" \ + "/srv/sig/${PRODUCT}/sigerp@.service" \ + && ln -snf \ + "/srv/sig/${PRODUCT}/sigerp@.service" \ + "/etc/systemd/system/sigerp@.service" \ + && ln -snf \ + "sigerp.service@" \ + "/etc/systemd/system/openerp@.service" - [[ -f "/srv/sig/${PRODUTO}/addons/requirements.txt" ]] && \ - runuser -l ${PRODUTO} -- \ - python -m pip install -r /srv/sig/${PRODUTO}/addons/requirements.txt --user - chown -R ${PRODUTO}: /srv/sig/${PRODUTO}/ + # Config file + download "installer/config/${PRODUCT}/sigerp-${_pdpy}.conf" \ + "/srv/sig/${PRODUCT}/config/sigerp.conf" + + # Artwork SigERP + download "installer/config/${PRODUCT}/artwork-sigerp.zip" \ + "${CACHEDIR}/${PRODUCT}/artwork-sigerp.zip" \ + && unzip -o -d \ + "/srv/sig/${PRODUCT}/.local/lib/python${_pdpy%.*}/site-packages/" \ + -x "${CACHEDIR}/${PRODUCT}/artwork-sigerp.zip" + + # Runtime dependencies + SIGERP_PACKAGES="\ + atop \ + libmysqlclient21 \ + net-tools \ + rclone \ + tmate \ + vim-nox \ + " + system.install_pkgs ${SIGERP_PACKAGES} + + # Create/Alter PostgreSQL user + local _dbuser="openerp" + local _password=$(openssl rand -base64 32 | sed 's/\//|/g') + ${ui}.status info $"Criando/Atualizando usuário do banco de dados [%s]" ${PRODUCT} + sudo -iu postgres \ + psql -c \ + "CREATE USER ${_dbuser} WITH \ + PASSWORD '${_password}' \ + CREATEDB;" \ + || \ + sudo -iu postgres \ + psql -c \ + "ALTER USER ${_dbuser} WITH \ + PASSWORD '${_password}' \ + CREATEDB;" + + if [[ 0${?} -eq 0 ]]; then + sed -i "s/.*db_password.*/db_password = ${_password}/g" \ + "/srv/sig/${PRODUCT}/config/sigerp.conf" + ${ui}.status warn $"Senha de acesso ao banco de dados: %s" ${_password} + sleep 5 + fi + + systemctl daemon-reload + systemctl enable --now sigerp.service || : ;; sigpdv) _date=$(date +%Y%m%d%H%M%S) - [[ -d "/srv/sig/${PRODUTO}/sigpdv" ]] && \ + + # -- Faz o backup da pasta anterior do SigPDV + [[ -d "/srv/sig/${PRODUCT}/sigpdv" ]] && \ mv \ - /srv/sig/${PRODUTO}/sigpdv \ - /srv/sig/${PRODUTO}/sigpdv.${_date}.bak + /srv/sig/${PRODUCT}/sigpdv \ + /srv/sig/${PRODUCT}/sigpdv.${_date}.bak - # PostgreSQL user and database - ${ui}.status info $"Criando usuário e banco de dados [%s]" ${PRODUTO} - sudo -i -u postgres createuser -d ${PRODUTO} >/dev/null 2>&1 || : - sudo -i -u postgres createdb -O ${PRODUTO} ${PRODUTO} >/dev/null 2>&1 || : - sudo -iu postgres psql -c "\password ${PRODUTO}" - ${ui}.status warn $"Não esqueça de alterar a senha no pdvconfig!" - # TODO: Simplificar essa baderna + # -- Cria a árvore de diretórios do SigPDV + mkdir -p /srv/sig/${PRODUCT}/sigpdv + mkdir -p /usr/local/sigext + mkdir -p /recebe + + # -- Instala pacotes necessários para rodar o programa SIGPV_PACKAGES=" atop \ + libmysqlclient21 \ mousepad \ net-tools \ qt5dxcb-plugin \ system-config-printer \ terminator \ + rclone \ tmate \ vim-nox \ " system.install_pkgs ${SIGPV_PACKAGES} - mkdir -p /srv/sig/${PRODUTO}/sigpdv - mkdir -p /usr/local/sigext - mkdir -p /recebe - - download "installer/config/${PRODUTO}/${PRODUTO}-single-instance-fix.patch" \ - "${CACHEDIR}/sigpdv/${PRODUTO}-single-instance-fix.patch" - - tar -C /srv/sig/${PRODUTO}/ \ - -xzf ${CACHEDIR}/${PRODUTO}/${PRODUTO}-${_pdpv#*/}.tar.gz - patch -d /srv/sig/${PRODUTO}/sigpdv \ - -p1 < "${CACHEDIR}/sigpdv/${PRODUTO}-single-instance-fix.patch" - - ln -snf /srv/sig/${PRODUTO}/sigpdv /usr/local/ - + # -- Download e instalação dos addons e aplicação de correções + tar -C /srv/sig/${PRODUCT}/ \ + -xzf ${CACHEDIR}/${PRODUCT}/${PRODUCT}-${_pdpv#*/}.tar.gz ln -snf \ - /srv/sig/${PRODUTO}/sigpdv \ + /srv/sig/${PRODUCT}/sigpdv \ /srv/sig/sigpdv/.local/lib/python2.7/site-packages/ + ln -snf \ + /srv/sig/${PRODUCT}/sigpdv \ + /usr/local/ + # Correção para erro "Dois frentes em execução" + download "installer/config/${PRODUCT}/${PRODUCT}-single-instance-fix.patch" \ + "${CACHEDIR}/sigpdv/${PRODUCT}-single-instance-fix.patch" + patch -d /srv/sig/${PRODUCT}/sigpdv \ + -p0 < "${CACHEDIR}/sigpdv/${PRODUCT}-single-instance-fix.patch" - mkdir /srv/sig/sigpdv/.local/lib/python2.7/site-packages/share \ - && mv /srv/sig/${PRODUTO}/.local/share/kiwi \ - /srv/sig/sigpdv/.local/lib/python2.7/site-packages/share/ \ - && ln -snf \ - /srv/sig/sigpdv/.local/lib/python2.7/site-packages/share/kiwi \ - /srv/sig/${PRODUTO}/.local/share/ \ + # -- Instalação dos módulos python de dependências + download "installer/config/${PRODUCT}/requirements.txt" \ + "/srv/sig/${PRODUCT}/sigpdv/requirements.txt" + [[ -f "/srv/sig/${PRODUCT}/sigpdv/requirements.txt" ]] && \ + runuser -l ${PRODUCT} -- \ + python -m pip install -qq -r /srv/sig/${PRODUCT}/sigpdv/requirements.txt --user \ + && rm -f /srv/sig/${PRODUCT}/sigpdv/requirements.txt - tar --transform="s|stoqdrivers/||" \ - -C /srv/sig/sigpdv/.local/lib/python2.7/site-packages/ \ - -xzf ${CACHEDIR}/${PRODUTO}/stoqdrivers-0.9.11.tar.gz \ - stoqdrivers/stoqdrivers - - download "installer/config/${PRODUTO}/requirements.txt" \ - "/srv/sig/${PRODUTO}/sigpdv/requirements.txt" - - download "installer/config/${PRODUTO}/${PRODUTO}-wrapper.sh" \ - "/srv/sig/${PRODUTO}/${PRODUTO}-wrapper.sh" \ - && chmod +x "/srv/sig/${PRODUTO}/${PRODUTO}-wrapper.sh" \ - && ln -snf "/srv/sig/${PRODUTO}/${PRODUTO}-wrapper.sh" /usr/local/bin/start-comanda \ - && ln -snf "/srv/sig/${PRODUTO}/${PRODUTO}-wrapper.sh" /usr/local/bin/start-consulta-cda \ - && ln -snf "/srv/sig/${PRODUTO}/${PRODUTO}-wrapper.sh" /usr/local/bin/start-pdvconfig \ - && ln -snf "/srv/sig/${PRODUTO}/${PRODUTO}-wrapper.sh" /usr/local/bin/start-sigpdv \ - && ln -snf "/srv/sig/${PRODUTO}/${PRODUTO}-wrapper.sh" /usr/local/bin/start-sigpve - - ln -snf /srv/sig/${PRODUTO}/${PRODUTO}/debian/icons/* \ + # -- Lançadores dos programas + download "installer/config/${PRODUCT}/${PRODUCT}-wrapper.sh" \ + "/srv/sig/${PRODUCT}/${PRODUCT}-wrapper.sh" \ + && chmod +x "/srv/sig/${PRODUCT}/${PRODUCT}-wrapper.sh" \ + && ln -snf "/srv/sig/${PRODUCT}/${PRODUCT}-wrapper.sh" /usr/local/bin/start-comanda \ + && ln -snf "/srv/sig/${PRODUCT}/${PRODUCT}-wrapper.sh" /usr/local/bin/start-consulta-cda \ + && ln -snf "/srv/sig/${PRODUCT}/${PRODUCT}-wrapper.sh" /usr/local/bin/start-pdvconfig \ + && ln -snf "/srv/sig/${PRODUCT}/${PRODUCT}-wrapper.sh" /usr/local/bin/start-sigpdv \ + && ln -snf "/srv/sig/${PRODUCT}/${PRODUCT}-wrapper.sh" /usr/local/bin/start-sigpve + ln -snf \ + /srv/sig/${PRODUCT}/${PRODUCT}/debian/icons/* \ /usr/share/pixmaps/ mkdir /usr/local/share/applications/ \ && ln -snf \ - /srv/sig/${PRODUTO}/${PRODUTO}/debian/desktop-files/* \ - /usr/local/share/applications/ \ - && sed -i 's|/usr/bin|/usr/local/bin|g' /usr/local/share/applications/*.desktop \ - && update-desktop-database || : + /srv/sig/${PRODUCT}/${PRODUCT}/debian/desktop-files/* \ + /usr/local/share/applications/ \ + && sed -i 's|/usr/bin|/usr/local/bin|g' /usr/local/share/applications/*.desktop \ + && update-desktop-database || : - download "installer/config/${PRODUTO}/${PRODUTO}.sudo" \ - "/etc/sudoers.d/${PRODUTO}" \ - && chown root:root "/etc/sudoers.d/${PRODUTO}" \ - && chmod 600 "/etc/sudoers.d/${PRODUTO}" - - download "installer/config/${PRODUTO}/pdvconfig.cfg" \ + # -- Configuração padrão inicial + download "installer/config/${PRODUCT}/pdvconfig.cfg" \ "/usr/local/sigext/pdvconfig.cfg" - - download "installer/config/${PRODUTO}/CliSiTef.ini" \ + download "installer/config/${PRODUCT}/CliSiTef.ini" \ "/usr/local/sigext/CliSiTef.ini" + for amb in homologacao producao lib_ssl_antiga; do + ln -snf \ + "/usr/local/sigext/CliSiTef.ini" \ + /srv/sig/${PRODUCT}/${PRODUCT}/sigtef/lib_x86_64/${amb}/ + done - chown -R ${PRODUTO}: /usr/local/sigext /recebe - chmod -R g+rw /usr/local/sigext /recebe - # End TODO + # -- Configurações de segurança e dos usuários + local _app_user=${PRODUCT} + local _app_group=${_app_user} + # Acesso do usuário do desktop + local _desktop_user=$(getent passwd | sed '/x:1000/!d;s/:.*//g') + usermod -aG ${_app_group},pyenv ${_desktop_user} + # Configuração do sudo + download "installer/config/${PRODUCT}/${PRODUCT}.sudo" \ + "/etc/sudoers.d/${PRODUCT}" \ + && chown root:root "/etc/sudoers.d/${PRODUCT}" \ + && chmod 600 "/etc/sudoers.d/${PRODUCT}" + # Permissões de usuários e grupos + for dir in /srv/sig/${PRODUCT} /usr/local/sigext /recebe; do + chown -R ${_app_user}:${_app_group} ${dir} + chmod -R g+rw,o-rwx ${dir} + done - [[ -f "/srv/sig/${PRODUTO}/sigpdv/requirements.txt" ]] && \ - runuser -l ${PRODUTO} -- \ - python -m pip install -qq -r /srv/sig/${PRODUTO}/sigpdv/requirements.txt --user \ - && rm -f /srv/sig/${PRODUTO}/sigpdv/requirements.txt - chown -R ${PRODUTO}: /srv/sig/${PRODUTO}/ - - # TODO : autodetect user - usermod -aG ${PRODUTO} caixa + # -- Configuração do banco de dados PostgreSQL + local _db_name=${PRODUCT} + local _db_user=${_db_name} + local _db_pass=$(openssl rand -base64 32 | sed 's/\//|/g') + ${ui}.status info $"Configurando o banco de dados [%s]" ${_db_name}} + sudo -iu postgres \ + psql -c \ + "CREATE USER ${_db_user} WITH \ + PASSWORD '${_db_pass}' \ + CREATEDB;" \ + || \ + sudo -iu postgres \ + psql -c \ + "ALTER USER ${_db_user} WITH \ + PASSWORD '${_db_pass}' \ + CREATEDB;" + if [[ 0${?} -eq 0 ]]; then + sed -i "s/.*db_pdv_pass.*/db_pdv_pass = ${_db_pass}/g" \ + "/usr/local/sigext/pdvconfig.cfg" + sudo -i -u postgres createdb -O ${_db_user} ${_db_name} >/dev/null 2>&1 || : + ${ui}.status warn $"Senha de acesso ao banco de dados: %s" ${_db_pass} + sleep 5 + fi ;; + sigvpn) - ${ui}.status warn $"Não implementado." -# rm -f /etc/apt/trusted.gpg.d/openvpn*.gpg -# curl -fsSL https://swupdate.openvpn.net/repos/repo-public.gpg \ -# | gpg --dearmor \ -# > /etc/apt/trusted.gpg.d/openvpn-repo-public.gpg -# -# rm -f /etc/apt/sources.list.d/openvpn*.list -# echo "deb [arch=amd64] https://build.openvpn.net/debian/openvpn/stable ${suite} main" \ -# > /etc/apt/sources.list.d/openvpn-aptrepo.list -# -# system.install_pkgs openvpn tmate \ -# && cd /etc/openvpn/client \ -# && (mv ../${name}.* . > /dev/null 2>&1 || true) \ -# && download "installer/config/openvpn/ovpn-local.ovpn" ${name}.conf \ -# && chown daemon:daemon ${name}.conf ${name}.passwd \ -# && systemctl disable openvpn.service \ -# && systemctl enable openvpn-client@${name}.service \ -# && systemctl restart openvpn-client@${name}.service \ -# && echo "net.ipv4.tcp_window_scaling=1" > /etc/sysctl.d/50-openvpn.conf \ -# && cd - + import /etc/os-release + + ${ui}.status info $"Configurando repositório OpenVPN ..." + local _name=suporte-sig + local _suite=${VERSION_CODENAME} + rm -f /etc/apt/trusted.gpg.d/openvpn*.gpg + curl -fsSL https://swupdate.openvpn.net/repos/repo-public.gpg \ + | gpg --dearmor \ + > /etc/apt/trusted.gpg.d/openvpn-repo-public.gpg + + rm -f /etc/apt/sources.list.d/openvpn*.list + echo "deb [arch=amd64] https://build.openvpn.net/debian/openvpn/stable ${_suite} main" \ + > /etc/apt/sources.list.d/openvpn-aptrepo.list + + ${ui}.status info $"Instalando pacotes..." + system.install_pkgs openvpn tmate + + ${ui}.status info $"Configurando serviço VPN ..." + while ! [[ -z "${_vpn_user}" ]]; do + local _vpn_user=$(${ui}.prompt $"Login de usuário da VPN: ") + done + + while ! [[ -z "${_vpn_pass}" ]]; do + local _vpn_pass=$(${ui}.prompt $"Senha do usuário da VPN: ") + done + echo -ne "${_vpn_user}\n${_vpn_pass}\n" > /etc/openvpn/client/${_name}.passwd \ + && cd /etc/openvpn/client \ + && (rm -rf ../${_name}.* >/dev/null 2>&1 || true) \ + && download "installer/config/openvpn/ovpn-local.ovpn" ${_name}.conf \ + && chown daemon:daemon ${_name}.conf ${_name}.passwd \ + && systemctl disable openvpn.service \ + && systemctl enable openvpn-client@${_name}.service \ + && systemctl restart openvpn-client@${_name}.service \ + && echo "net.ipv4.tcp_window_scaling=1" > /etc/sysctl.d/50-openvpn.conf \ + && cd - ;; esac - system.remove_pkgs ${BUILD_PACKAGES} + #system.remove_pkgs ${BUILD_PACKAGES} ${ui}.color none - ${ui}.status info $"Instalação concluída. Reinicie o computador." + ${ui}.status info $"Instalação concluída. REINICIE o computador." ${ui}.prompt $"Pressione ENTER para continuar ... " } - - - -function sig.setup_artwork { - return -} - -function sig.setup_sigtef { +function product.sigpdv.setup_sigtef { local _sigtedir="/sig/sigpdv/sigtef/lib_x86_64" sudo echo "${sigtefdir}/" \ @@ -809,39 +1111,50 @@ function sig.setup_sigtef { } - # == Loop Principal =======================================================================+===== # -clear +#clear export LANG=${LANG:-'C.UTF-8'} -${ui}.init $"%s [VERSÃO: %s] - CONFIGURAÇÃO INICIAL\n" ${self^^} ${version} +#${ui}.init $"%s [VERSÃO: %s] - CONFIGURAÇÃO INICIAL\n" ${self^^} ${version} -self.check_essential +#self.check_essential # -- Configuração do sistema -${ui}.title $"Reconfigurando o sistema operacional" -system.check_os -system.check_sudo -system.setlocale -system.check_net -system.setup_ntp +#${ui}.title $"Reconfigurando o sistema operacional" +#system.check_os +#system.check_sudo +#system.setlocale +#system.check_net +#system.setup_ntp -${ui}.title $"Instalando e configurando serviços" -system.install_postgres 17 citus-13.0 -system.install_pyenv /usr/local/share/pyenv 2.7.18 +#${ui}.title $"Instalando e configurando serviços" +#system.install_postgres 17 citus-13.0 +#system.install_pyenv /usr/local/share/pyenv 2.7.18 -${ui}.title $"Configurando contas de usuários" -system.create_user sig dialout,pyenv,sudo +#${ui}.title $"Configurando contas de usuários" +#system.create_user sig dialout,pyenv,sudo -${ui}.status info $"CONFIGURAÇÃO INICIAL CONCLUÍDA!" -${ui}.init "" -${ui}.prompt $"Pressione ENTER para continuar ... " +#${ui}.status info $"CONFIGURAÇÃO INICIAL CONCLUÍDA!" +#${ui}.init "" +#${ui}.prompt $"Pressione ENTER para continuar ... " CACHEDIR=$(mktemp -d /tmp/${self}.cache.XXXXX) +PRIVKEY_PASSPHRASE= + +# Menu while true; do - menu.produtos - produto.download - produto.install + PRODUCT= + installer.product.menu + + REPOS= + REQUIRES= + BUILD_REQUIRES= + DOWNLOADS= + product.get_requires + + #product.setup_repos + product.download + product.install done exit 0