moved docs
Switching to using vendored shell framework moved SafeDownload to vendored shell framework repo
This commit is contained in:
@@ -1,3 +0,0 @@
|
|||||||
#Global Variables used by the framework
|
|
||||||
|
|
||||||
export ProjectIncludes="1"
|
|
@@ -1,19 +0,0 @@
|
|||||||
#Place (primary/unique) key as very first argument on each record below
|
|
||||||
|
|
||||||
#Value Fields are (in order), (reference KEY_(VARIABLE) names in the code):
|
|
||||||
#1)valuex (description)
|
|
||||||
#2)valuey (description)
|
|
||||||
#3)valuez (description)
|
|
||||||
|
|
||||||
#An example:
|
|
||||||
#unique key of serverfqdn
|
|
||||||
#key of: subnet , value of: 10.10.10.0/24
|
|
||||||
#key of: gateway, value of: 10.10.10.1
|
|
||||||
|
|
||||||
#serverfqdn,10.10.10.0/24,10.10.10.1
|
|
||||||
|
|
||||||
#Place your records below:
|
|
||||||
|
|
||||||
#primary/uniquekey,#value
|
|
||||||
primarykey1,valuex,valuey,valuez
|
|
||||||
primarykey2,valuex,valuey,valuez
|
|
@@ -1,261 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Configuration Validation Framework
|
|
||||||
# Pre-flight checks for system compatibility and requirements
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# Source framework dependencies
|
|
||||||
source "$(dirname "${BASH_SOURCE[0]}")/PrettyPrint.sh" 2>/dev/null || echo "Warning: PrettyPrint.sh not found"
|
|
||||||
source "$(dirname "${BASH_SOURCE[0]}")/Logging.sh" 2>/dev/null || echo "Warning: Logging.sh not found"
|
|
||||||
|
|
||||||
# Configuration validation settings
|
|
||||||
declare -g VALIDATION_FAILED=0
|
|
||||||
declare -g VALIDATION_WARNINGS=0
|
|
||||||
|
|
||||||
# System requirements
|
|
||||||
declare -g MIN_RAM_GB=2
|
|
||||||
declare -g MIN_DISK_GB=10
|
|
||||||
declare -g REQUIRED_COMMANDS=("curl" "wget" "git" "systemctl" "apt-get" "dmidecode")
|
|
||||||
|
|
||||||
# Network endpoints to validate
|
|
||||||
declare -g REQUIRED_ENDPOINTS=(
|
|
||||||
"https://archive.ubuntu.com"
|
|
||||||
"https://linux.dell.com"
|
|
||||||
"https://download.proxmox.com"
|
|
||||||
"https://github.com"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Validation functions
|
|
||||||
function validate_system_requirements() {
|
|
||||||
print_info "Validating system requirements..."
|
|
||||||
|
|
||||||
# Check RAM
|
|
||||||
local total_mem_kb=$(grep MemTotal /proc/meminfo | awk '{print $2}')
|
|
||||||
local total_mem_gb=$((total_mem_kb / 1024 / 1024))
|
|
||||||
|
|
||||||
if [[ $total_mem_gb -ge $MIN_RAM_GB ]]; then
|
|
||||||
print_success "RAM requirement met: ${total_mem_gb}GB >= ${MIN_RAM_GB}GB"
|
|
||||||
else
|
|
||||||
print_error "RAM requirement not met: ${total_mem_gb}GB < ${MIN_RAM_GB}GB"
|
|
||||||
((VALIDATION_FAILED++))
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check disk space
|
|
||||||
local available_gb=$(df / | tail -1 | awk '{print int($4/1024/1024)}')
|
|
||||||
|
|
||||||
if [[ $available_gb -ge $MIN_DISK_GB ]]; then
|
|
||||||
print_success "Disk space requirement met: ${available_gb}GB >= ${MIN_DISK_GB}GB"
|
|
||||||
else
|
|
||||||
print_error "Disk space requirement not met: ${available_gb}GB < ${MIN_DISK_GB}GB"
|
|
||||||
((VALIDATION_FAILED++))
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate_required_commands() {
|
|
||||||
print_info "Validating required commands..."
|
|
||||||
|
|
||||||
for cmd in "${REQUIRED_COMMANDS[@]}"; do
|
|
||||||
if command -v "$cmd" >/dev/null 2>&1; then
|
|
||||||
print_success "Required command available: $cmd"
|
|
||||||
else
|
|
||||||
print_error "Required command missing: $cmd"
|
|
||||||
((VALIDATION_FAILED++))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate_os_compatibility() {
|
|
||||||
print_info "Validating OS compatibility..."
|
|
||||||
|
|
||||||
if [[ -f /etc/os-release ]]; then
|
|
||||||
local os_id=$(grep "^ID=" /etc/os-release | cut -d'=' -f2 | tr -d '"')
|
|
||||||
local os_version=$(grep "^VERSION_ID=" /etc/os-release | cut -d'=' -f2 | tr -d '"')
|
|
||||||
|
|
||||||
case "$os_id" in
|
|
||||||
ubuntu)
|
|
||||||
if [[ "${os_version%%.*}" -ge 18 ]]; then
|
|
||||||
print_success "OS compatibility: Ubuntu $os_version (fully supported)"
|
|
||||||
else
|
|
||||||
print_warning "OS compatibility: Ubuntu $os_version (may have issues)"
|
|
||||||
((VALIDATION_WARNINGS++))
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
debian)
|
|
||||||
if [[ "${os_version%%.*}" -ge 10 ]]; then
|
|
||||||
print_success "OS compatibility: Debian $os_version (fully supported)"
|
|
||||||
else
|
|
||||||
print_warning "OS compatibility: Debian $os_version (may have issues)"
|
|
||||||
((VALIDATION_WARNINGS++))
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
print_warning "OS compatibility: $os_id $os_version (not tested, may work)"
|
|
||||||
((VALIDATION_WARNINGS++))
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
else
|
|
||||||
print_error "Cannot determine OS version"
|
|
||||||
((VALIDATION_FAILED++))
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate_network_connectivity() {
|
|
||||||
print_info "Validating network connectivity..."
|
|
||||||
|
|
||||||
for endpoint in "${REQUIRED_ENDPOINTS[@]}"; do
|
|
||||||
if curl -s --connect-timeout 10 --max-time 30 --head "$endpoint" >/dev/null 2>&1; then
|
|
||||||
print_success "Network connectivity: $endpoint"
|
|
||||||
else
|
|
||||||
print_error "Network connectivity failed: $endpoint"
|
|
||||||
((VALIDATION_FAILED++))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate_permissions() {
|
|
||||||
print_info "Validating system permissions..."
|
|
||||||
|
|
||||||
local required_dirs=("/etc" "/usr/local/bin" "/var/log")
|
|
||||||
|
|
||||||
for dir in "${required_dirs[@]}"; do
|
|
||||||
if [[ -w "$dir" ]]; then
|
|
||||||
print_success "Write permission: $dir"
|
|
||||||
else
|
|
||||||
print_error "Write permission denied: $dir (run with sudo)"
|
|
||||||
((VALIDATION_FAILED++))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate_conflicting_software() {
|
|
||||||
print_info "Checking for conflicting software..."
|
|
||||||
|
|
||||||
# Check for conflicting SSH configurations
|
|
||||||
if [[ -f /etc/ssh/sshd_config ]]; then
|
|
||||||
if grep -q "^PasswordAuthentication yes" /etc/ssh/sshd_config; then
|
|
||||||
print_warning "SSH password authentication is enabled (will be disabled)"
|
|
||||||
((VALIDATION_WARNINGS++))
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for conflicting firewall rules
|
|
||||||
if command -v ufw >/dev/null 2>&1; then
|
|
||||||
if ufw status | grep -q "Status: active"; then
|
|
||||||
print_warning "UFW firewall is active (may conflict with iptables rules)"
|
|
||||||
((VALIDATION_WARNINGS++))
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for conflicting SNMP configurations
|
|
||||||
if systemctl is-active snmpd >/dev/null 2>&1; then
|
|
||||||
print_warning "SNMP service is already running (will be reconfigured)"
|
|
||||||
((VALIDATION_WARNINGS++))
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate_hardware_compatibility() {
|
|
||||||
print_info "Validating hardware compatibility..."
|
|
||||||
|
|
||||||
# Check if this is a Dell server
|
|
||||||
if [[ "$IS_PHYSICAL_HOST" -gt 0 ]]; then
|
|
||||||
print_info "Dell physical server detected - OMSA will be installed"
|
|
||||||
else
|
|
||||||
print_info "Virtual machine detected - hardware-specific tools will be skipped"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for virtualization
|
|
||||||
if grep -q "hypervisor" /proc/cpuinfo; then
|
|
||||||
print_info "Virtualization detected - optimizations will be applied"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate_existing_users() {
|
|
||||||
print_info "Validating user configuration..."
|
|
||||||
|
|
||||||
# Check for existing users
|
|
||||||
if [[ "$LOCALUSER_CHECK" -gt 0 ]]; then
|
|
||||||
print_info "User 'localuser' already exists"
|
|
||||||
else
|
|
||||||
print_info "User 'localuser' will be created"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$SUBODEV_CHECK" -gt 0 ]]; then
|
|
||||||
print_info "User 'subodev' already exists"
|
|
||||||
else
|
|
||||||
print_info "User 'subodev' will be created"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function validate_security_requirements() {
|
|
||||||
print_info "Validating security requirements..."
|
|
||||||
|
|
||||||
# Check if running as root
|
|
||||||
if [[ $EUID -eq 0 ]]; then
|
|
||||||
print_success "Running with root privileges"
|
|
||||||
else
|
|
||||||
print_error "Must run with root privileges (use sudo)"
|
|
||||||
((VALIDATION_FAILED++))
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for existing SSH keys
|
|
||||||
if [[ -f ~/.ssh/id_rsa ]]; then
|
|
||||||
print_warning "SSH keys already exist - will be preserved"
|
|
||||||
((VALIDATION_WARNINGS++))
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for secure boot
|
|
||||||
if [[ -d /sys/firmware/efi/efivars ]]; then
|
|
||||||
print_info "UEFI system detected"
|
|
||||||
if mokutil --sb-state 2>/dev/null | grep -q "SecureBoot enabled"; then
|
|
||||||
print_warning "Secure Boot is enabled - may affect kernel modules"
|
|
||||||
((VALIDATION_WARNINGS++))
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Main validation function
|
|
||||||
function run_configuration_validation() {
|
|
||||||
print_header "Configuration Validation"
|
|
||||||
|
|
||||||
# Reset counters
|
|
||||||
VALIDATION_FAILED=0
|
|
||||||
VALIDATION_WARNINGS=0
|
|
||||||
|
|
||||||
# Run all validation checks
|
|
||||||
validate_system_requirements
|
|
||||||
validate_required_commands
|
|
||||||
validate_os_compatibility
|
|
||||||
validate_network_connectivity
|
|
||||||
validate_permissions
|
|
||||||
validate_conflicting_software
|
|
||||||
validate_hardware_compatibility
|
|
||||||
validate_existing_users
|
|
||||||
validate_security_requirements
|
|
||||||
|
|
||||||
# Summary
|
|
||||||
print_header "Validation Summary"
|
|
||||||
|
|
||||||
if [[ $VALIDATION_FAILED -eq 0 ]]; then
|
|
||||||
print_success "All validation checks passed"
|
|
||||||
if [[ $VALIDATION_WARNINGS -gt 0 ]]; then
|
|
||||||
print_warning "$VALIDATION_WARNINGS warnings - deployment may continue"
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
print_error "$VALIDATION_FAILED validation checks failed"
|
|
||||||
if [[ $VALIDATION_WARNINGS -gt 0 ]]; then
|
|
||||||
print_warning "$VALIDATION_WARNINGS additional warnings"
|
|
||||||
fi
|
|
||||||
print_error "Please resolve the above issues before deployment"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Export functions for use in other scripts
|
|
||||||
export -f validate_system_requirements
|
|
||||||
export -f validate_required_commands
|
|
||||||
export -f validate_os_compatibility
|
|
||||||
export -f validate_network_connectivity
|
|
||||||
export -f validate_permissions
|
|
||||||
export -f run_configuration_validation
|
|
@@ -1,33 +0,0 @@
|
|||||||
function DebugMe() {
|
|
||||||
[[ $script_debug = 1 ]] && "$@" || :
|
|
||||||
|
|
||||||
#to turn debugging on, set script_debug=1
|
|
||||||
#to turn debugging off, set script_debug=0
|
|
||||||
|
|
||||||
# be sure to append || : or || true here or use return 0, since the return code
|
|
||||||
# of this function should always be 0 to not influence anything else with an unwanted
|
|
||||||
# "false" return code (for example the script's exit code if this function is used
|
|
||||||
# as the very last command in the script)
|
|
||||||
|
|
||||||
#This function does nothing when script_debug is unset or empty, but it executes the
|
|
||||||
#given parameters as commands when script_debug is set. Use it like this:
|
|
||||||
|
|
||||||
#debugme logger "Sorting the database"
|
|
||||||
#database_sort
|
|
||||||
#debugme logger "Finished sorting the database, exit code $?"
|
|
||||||
|
|
||||||
|
|
||||||
# * print commands to be executed to stderr as if they were read from input
|
|
||||||
# (script file or keyboard)
|
|
||||||
# * print everything before any ( substitution and expansion, …) is applied
|
|
||||||
set -v
|
|
||||||
|
|
||||||
# * print everything as if it were executed, after substitution and expansion is applied
|
|
||||||
# * indicate the depth-level of the subshell (by default by prefixing a + (plus) sign to
|
|
||||||
# the displayed command)
|
|
||||||
# * indicate the recognized words after word splitting by marking them like 'x y'
|
|
||||||
# * in shell version 4.1, this debug output can be printed to a configurable file
|
|
||||||
#descriptor, rather than sdtout by setting the BASH_XTRACEFD variable.
|
|
||||||
set -x
|
|
||||||
|
|
||||||
}
|
|
@@ -1,55 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Standard strict mode and error handling/tracing boilderplate..
|
|
||||||
|
|
||||||
# This is a function I include and execute in every shell script that I write.
|
|
||||||
# It sets up a bunch of error handling odds and ends
|
|
||||||
|
|
||||||
# Bits and pieces Sourced from (as best I recall):
|
|
||||||
# * https://news.ycombinator.com/item?id=24727495
|
|
||||||
# * many other hacker news / slashdot etc posts over the years
|
|
||||||
# * https://www.tothenew.com/blog/foolproof-your-bash-script-some-best-practices/
|
|
||||||
# * https://translucentcomputing.com/2020/05/unofficial-bash-strict-mode-errexit/
|
|
||||||
# * http://redsymbol.net/articles/unofficial-bash-strict-mode/
|
|
||||||
# * the school of hard knocks... (aka my code failures...)
|
|
||||||
|
|
||||||
#Here's the beef (as the commercial says..)
|
|
||||||
|
|
||||||
export PS4='(${BASH_SOURCE}:${LINENO}): - [${SHLVL},${BASH_SUBSHELL},$?] $ '
|
|
||||||
|
|
||||||
function error_out()
|
|
||||||
{
|
|
||||||
print_error "$1"
|
|
||||||
print_error "Bailing out. See above for reason...."
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
function handle_failure() {
|
|
||||||
local lineno=$1
|
|
||||||
local fn=$2
|
|
||||||
local exitstatus=$3
|
|
||||||
local msg=$4
|
|
||||||
local lineno_fns=${0% 0}
|
|
||||||
if [[ "$lineno_fns" != "-1" ]] ; then
|
|
||||||
lineno="${lineno} ${lineno_fns}"
|
|
||||||
fi
|
|
||||||
echo "${BASH_SOURCE[0]}: Function: ${fn} Line Number : [${lineno}] Failed with status ${exitstatus}: $msg"
|
|
||||||
}
|
|
||||||
|
|
||||||
trap 'handle_failure "${BASH_LINENO[*]}" "$LINENO" "${FUNCNAME[*]:-script}" "$?" "$BASH_COMMAND"' ERR
|
|
||||||
|
|
||||||
#use errexit (a.k.a. set -e) to make your script exit when a command fails.
|
|
||||||
#add || true to commands that you allow to fail.
|
|
||||||
set -o errexit
|
|
||||||
|
|
||||||
# Use set -o nounset (a.k.a. set -u) to exit when your script tries to use undeclared
|
|
||||||
# variables.
|
|
||||||
set -o nounset
|
|
||||||
|
|
||||||
#Use set -o pipefail in scripts to catch (for example) mysqldump fails
|
|
||||||
#in e.g. mysqldump |gzip.
|
|
||||||
#The exit status of the last command that threw a non-zero exit code is returned
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
#Function tracing...
|
|
||||||
set -o functrace
|
|
@@ -1,5 +0,0 @@
|
|||||||
export CURRENT_TIMESTAMP
|
|
||||||
CURRENT_TIMESTAMP="$(date +%A-%Y-%m-%d-%T)"
|
|
||||||
|
|
||||||
export LOGFILENAME
|
|
||||||
LOGFILENAME="${PROJECT_ROOT_PATH}/logs/$0.${CURRENT_TIMESTAMP}.$$"
|
|
@@ -1,15 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
function LookupKV()
|
|
||||||
{
|
|
||||||
|
|
||||||
echo "KV lookup..."
|
|
||||||
|
|
||||||
#Arguments:
|
|
||||||
#$1 <path to key/value table>
|
|
||||||
#$2 unique record identifier
|
|
||||||
|
|
||||||
#Returns:
|
|
||||||
#Variable/array containing all the values in the record
|
|
||||||
|
|
||||||
}
|
|
@@ -1,20 +0,0 @@
|
|||||||
function print_info()
|
|
||||||
{
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
NC='\033[0m'
|
|
||||||
tput bold
|
|
||||||
echo -e "$GREEN $1${NC}"
|
|
||||||
echo -e "$GREEN $1${NC}" >> "$LOGFILENAME"
|
|
||||||
tput sgr0
|
|
||||||
}
|
|
||||||
|
|
||||||
function print_error()
|
|
||||||
{
|
|
||||||
RED='\033[0;31m'
|
|
||||||
NC='\033[0m'
|
|
||||||
tput bold
|
|
||||||
echo -e "$RED $1${NC}"
|
|
||||||
echo -e "$RED $1${NC}" >> "$LOGFILENAME"
|
|
||||||
echo "$1"
|
|
||||||
tput sgr0
|
|
||||||
}
|
|
@@ -1,273 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Safe Download Framework
|
|
||||||
# Provides robust download operations with error handling, retries, and validation
|
|
||||||
# Author: TSYS Development Team
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# Source framework dependencies
|
|
||||||
source "$(dirname "${BASH_SOURCE[0]}")/PrettyPrint.sh" 2>/dev/null || echo "Warning: PrettyPrint.sh not found"
|
|
||||||
source "$(dirname "${BASH_SOURCE[0]}")/Logging.sh" 2>/dev/null || echo "Warning: Logging.sh not found"
|
|
||||||
|
|
||||||
# Download configuration
|
|
||||||
declare -g DOWNLOAD_TIMEOUT=60
|
|
||||||
declare -g DOWNLOAD_CONNECT_TIMEOUT=30
|
|
||||||
declare -g DOWNLOAD_MAX_ATTEMPTS=3
|
|
||||||
declare -g DOWNLOAD_RETRY_DELAY=5
|
|
||||||
|
|
||||||
# Safe download with retry logic and error handling
|
|
||||||
function safe_download() {
|
|
||||||
local url="$1"
|
|
||||||
local dest="$2"
|
|
||||||
local expected_checksum="${3:-}"
|
|
||||||
local max_attempts="${4:-$DOWNLOAD_MAX_ATTEMPTS}"
|
|
||||||
|
|
||||||
local attempt=1
|
|
||||||
local temp_file="${dest}.tmp.$$"
|
|
||||||
|
|
||||||
# Validate inputs
|
|
||||||
if [[ -z "$url" || -z "$dest" ]]; then
|
|
||||||
print_error "safe_download: URL and destination are required"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create destination directory if needed
|
|
||||||
local dest_dir
|
|
||||||
dest_dir="$(dirname "$dest")"
|
|
||||||
if [[ ! -d "$dest_dir" ]]; then
|
|
||||||
if ! mkdir -p "$dest_dir"; then
|
|
||||||
print_error "Failed to create directory: $dest_dir"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
print_info "Downloading: $(basename "$dest") from $url"
|
|
||||||
|
|
||||||
while [[ $attempt -le $max_attempts ]]; do
|
|
||||||
if curl --silent --show-error --fail \
|
|
||||||
--connect-timeout "$DOWNLOAD_CONNECT_TIMEOUT" \
|
|
||||||
--max-time "$DOWNLOAD_TIMEOUT" \
|
|
||||||
--location \
|
|
||||||
--user-agent "TSYS-FetchApply/1.0" \
|
|
||||||
"$url" > "$temp_file"; then
|
|
||||||
|
|
||||||
# Verify checksum if provided
|
|
||||||
if [[ -n "$expected_checksum" ]]; then
|
|
||||||
if verify_checksum "$temp_file" "$expected_checksum"; then
|
|
||||||
mv "$temp_file" "$dest"
|
|
||||||
print_success "Downloaded and verified: $(basename "$dest")"
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
print_error "Checksum verification failed for: $(basename "$dest")"
|
|
||||||
rm -f "$temp_file"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
mv "$temp_file" "$dest"
|
|
||||||
print_success "Downloaded: $(basename "$dest")"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
print_warning "Download attempt $attempt failed: $(basename "$dest")"
|
|
||||||
rm -f "$temp_file"
|
|
||||||
|
|
||||||
if [[ $attempt -lt $max_attempts ]]; then
|
|
||||||
print_info "Retrying in ${DOWNLOAD_RETRY_DELAY}s..."
|
|
||||||
sleep "$DOWNLOAD_RETRY_DELAY"
|
|
||||||
fi
|
|
||||||
|
|
||||||
((attempt++))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
print_error "Failed to download after $max_attempts attempts: $(basename "$dest")"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Verify file checksum
|
|
||||||
function verify_checksum() {
|
|
||||||
local file="$1"
|
|
||||||
local expected_checksum="$2"
|
|
||||||
|
|
||||||
if [[ ! -f "$file" ]]; then
|
|
||||||
print_error "File not found for checksum verification: $file"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local actual_checksum
|
|
||||||
actual_checksum=$(sha256sum "$file" | cut -d' ' -f1)
|
|
||||||
|
|
||||||
if [[ "$actual_checksum" == "$expected_checksum" ]]; then
|
|
||||||
print_success "Checksum verified: $(basename "$file")"
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
print_error "Checksum mismatch for $(basename "$file")"
|
|
||||||
print_error "Expected: $expected_checksum"
|
|
||||||
print_error "Actual: $actual_checksum"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Batch download multiple files
|
|
||||||
function batch_download() {
|
|
||||||
local -n download_map=$1
|
|
||||||
local failed_downloads=0
|
|
||||||
|
|
||||||
print_info "Starting batch download of ${#download_map[@]} files..."
|
|
||||||
|
|
||||||
for url in "${!download_map[@]}"; do
|
|
||||||
local dest="${download_map[$url]}"
|
|
||||||
if ! safe_download "$url" "$dest"; then
|
|
||||||
((failed_downloads++))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ $failed_downloads -eq 0 ]]; then
|
|
||||||
print_success "All batch downloads completed successfully"
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
print_error "$failed_downloads batch downloads failed"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Download with progress indication for large files
|
|
||||||
function safe_download_with_progress() {
|
|
||||||
local url="$1"
|
|
||||||
local dest="$2"
|
|
||||||
local expected_checksum="${3:-}"
|
|
||||||
|
|
||||||
print_info "Downloading with progress: $(basename "$dest")"
|
|
||||||
|
|
||||||
if curl --progress-bar --show-error --fail \
|
|
||||||
--connect-timeout "$DOWNLOAD_CONNECT_TIMEOUT" \
|
|
||||||
--max-time "$DOWNLOAD_TIMEOUT" \
|
|
||||||
--location \
|
|
||||||
--user-agent "TSYS-FetchApply/1.0" \
|
|
||||||
"$url" -o "$dest"; then
|
|
||||||
|
|
||||||
# Verify checksum if provided
|
|
||||||
if [[ -n "$expected_checksum" ]]; then
|
|
||||||
if verify_checksum "$dest" "$expected_checksum"; then
|
|
||||||
print_success "Downloaded and verified: $(basename "$dest")"
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
rm -f "$dest"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
print_success "Downloaded: $(basename "$dest")"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
print_error "Failed to download: $(basename "$dest")"
|
|
||||||
rm -f "$dest"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check if URL is accessible
|
|
||||||
function check_url_accessibility() {
|
|
||||||
local url="$1"
|
|
||||||
|
|
||||||
if curl --silent --head --fail \
|
|
||||||
--connect-timeout "$DOWNLOAD_CONNECT_TIMEOUT" \
|
|
||||||
--max-time 10 \
|
|
||||||
"$url" >/dev/null 2>&1; then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Validate all required URLs before starting deployment
|
|
||||||
function validate_required_urls() {
|
|
||||||
local -a urls=("$@")
|
|
||||||
local failed_urls=0
|
|
||||||
|
|
||||||
print_info "Validating accessibility of ${#urls[@]} URLs..."
|
|
||||||
|
|
||||||
for url in "${urls[@]}"; do
|
|
||||||
if check_url_accessibility "$url"; then
|
|
||||||
print_success "✓ $url"
|
|
||||||
else
|
|
||||||
print_error "✗ $url"
|
|
||||||
((failed_urls++))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ $failed_urls -eq 0 ]]; then
|
|
||||||
print_success "All URLs are accessible"
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
print_error "$failed_urls URLs are not accessible"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Download configuration files with backup
|
|
||||||
function safe_config_download() {
|
|
||||||
local url="$1"
|
|
||||||
local dest="$2"
|
|
||||||
local backup_suffix="${3:-.bak.$(date +%Y%m%d-%H%M%S)}"
|
|
||||||
|
|
||||||
# Backup existing file if it exists
|
|
||||||
if [[ -f "$dest" ]]; then
|
|
||||||
local backup_file="${dest}${backup_suffix}"
|
|
||||||
if cp "$dest" "$backup_file"; then
|
|
||||||
print_info "Backed up existing config: $backup_file"
|
|
||||||
else
|
|
||||||
print_error "Failed to backup existing config: $dest"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Download new configuration
|
|
||||||
if safe_download "$url" "$dest"; then
|
|
||||||
print_success "Configuration updated: $(basename "$dest")"
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
# Restore backup if download failed and backup exists
|
|
||||||
local backup_file="${dest}${backup_suffix}"
|
|
||||||
if [[ -f "$backup_file" ]]; then
|
|
||||||
if mv "$backup_file" "$dest"; then
|
|
||||||
print_warning "Restored backup after failed download: $(basename "$dest")"
|
|
||||||
else
|
|
||||||
print_error "Failed to restore backup: $(basename "$dest")"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Test network connectivity to common endpoints
|
|
||||||
function test_network_connectivity() {
|
|
||||||
local test_urls=(
|
|
||||||
"https://archive.ubuntu.com"
|
|
||||||
"https://github.com"
|
|
||||||
"https://curl.haxx.se"
|
|
||||||
)
|
|
||||||
|
|
||||||
print_info "Testing network connectivity..."
|
|
||||||
|
|
||||||
for url in "${test_urls[@]}"; do
|
|
||||||
if check_url_accessibility "$url"; then
|
|
||||||
print_success "Network connectivity confirmed: $url"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
print_error "No network connectivity detected"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Export functions for use in other scripts
|
|
||||||
export -f safe_download
|
|
||||||
export -f verify_checksum
|
|
||||||
export -f batch_download
|
|
||||||
export -f safe_download_with_progress
|
|
||||||
export -f check_url_accessibility
|
|
||||||
export -f validate_required_urls
|
|
||||||
export -f safe_config_download
|
|
||||||
export -f test_network_connectivity
|
|
Reference in New Issue
Block a user