From a25e953f3fac01d1febc1921c985c7f1e6663d03 Mon Sep 17 00:00:00 2001 From: Garth Johnson Date: Sun, 31 Dec 2023 01:23:39 -0800 Subject: [PATCH] Closer to full baseline (#10) * rm duplicates added rsync * added bzip, pw10 theme ownership, and consistant ADD over COPY * adding ownership and history plugin as well as rc files * codespace font setting * Coder (#6) * moar promptiness * more compatible with lesser fonting * add user to docker group * corrected docker lib reference * added dockerinfo to tasks * better separation of build env * Testing with badges and adding notes * Testing with badges and adding notes * changed workflow names * changed from app to dev container name * fixed indent filure * indenting * versioning test * removed bad version test * added Docker test tasks * added docker test tasks --- src/broker_preflight.sh | 239 ++++++++++++++++++++++++++++++++++++++++ src/tasks.py | 124 +++++++++++++++------ 2 files changed, 327 insertions(+), 36 deletions(-) create mode 100755 src/broker_preflight.sh diff --git a/src/broker_preflight.sh b/src/broker_preflight.sh new file mode 100755 index 0000000..dcc6d4c --- /dev/null +++ b/src/broker_preflight.sh @@ -0,0 +1,239 @@ +#!/usr/bin/env bash +#set -e + +DEBUG=${DEBUG:=false} +if $DEBUG; then + echo "Debug on, all commands will be displayed" + set -x +fi + +# Archfx Broker for linux installation script +# +# See ... for the installation steps +# +# This script is meant for quick and easy setup of your Broker environment via: +# $ curl -fsSL https://private-sw-downloads.s3.amazonaws.com/archfx_broker/preflight/broker_preflight.sh -o broker_preflight.sh && chmod +x broker_preflight.sh +# $ ./broker_preflight.sh check +# $ ./broker_preflight.sh report +# + +# Variables +readonly ME=$(basename "$0") + +readonly BASE_DIR=${BASE_DIR:-'/opt'} +readonly INST_DIR=${INST_DIR:-$BASE_DIR/archfx} +readonly DEPLOY_DIR=$INST_DIR/broker +readonly DOCKER_CFG_DIR=/etc/docker +OFFLINE=${OFFLINE:=false} + + +####################################### +# Output CMDs +####################################### +function _banner_msg () { + echo -e "\n$@" +} +function _success_msg () { + echo -e "$@" +} +function _failure_msg () { + echo -e "FAILURE: $@" + exit 1 +} +function _warning_msg () { + echo "WARNING: $@" +} + + +####################################### +# DOCKER COMMANDS +####################################### +function _where_is_docker() { + ### Get docker insallation location ### + echo $( which docker ) +} + + +function _docker_root_dir() { + ### Get docker root dir ### + root_dir=$(docker info | grep 'Docker Root Dir:' | cut -d " " -f5) + echo $root_dir +} + + +function _is_docker_running() { + echo $(docker --version) +} + + +function _is_loki_plugin_installed() { + echo $(docker plugin ls | grep loki) +} + + +####################################### +# Inspect OS +####################################### +function _get_distribution() { + ### Save distro to logfile ### + local lsb_dist="" + # Every system that we officially support has /etc/os-release + if [ -r /etc/os-release ]; then + lsb_dist="$(. /etc/os-release && echo "$ID")" + fi + echo "$lsb_dist" +} + + +function _get_distro_version() { + ### Save distro version ### + local lsb_dist_id="" + # Every system that we officially support has /etc/os-release + if [ -r /etc/os-release ]; then + lsb_dist_id="$(. /etc/os-release && echo "$VERSION_ID")" + fi + echo "$lsb_dist_id" +} + + +function _get_dir_size() { + ### Save distro to logfile ### + dir=$1 + local directory_size=$(df ${dir} | awk 'NR==2 {print $4}') + echo $directory_size +} + + +#################### +# Other +#################### +function _outbound_connections() { + ### Check if we can get info from the server ### + url=$1 + expected=$2 + if $OFFLINE;then + echo -e "no" + else + response=$(curl -L -s -o /dev/null -w "%{http_code}" $url) + if (( $response == $expected )); then + connect="yes" + else + connect="no (response code: $response)" + fi + fi + echo $connect +} + + +####################################### +# Verifiy basic requirements +####################################### +function preflight_checks() { + ### Checks to see everything is as we want + # Arguments: + # log_file = where to save the data + # + # Output: + # logs_${EPOCH}.txt = formatted output + ### + _banner_msg "Running pre-flight checks" + + local -ir minute=$(date -u +%s) + local log_file="$PWD/logs_$minute.txt" + _success_msg "\tGenerating log file: $log_file" + + echo -e "date:" | tee "$log_file" + echo -e "\tlocal: $(date)" | tee -a "$log_file" + echo -e "\tutc: $(date -u +%s)" | tee -a "$log_file" + + echo -e "vm:" | tee -a "$log_file" + echo -e "\thost: $(hostname)" | tee -a "$log_file" + lsb_dist=$(_get_distribution "$log_file") + echo -e "\tdistribution: $lsb_dist" | tee -a "$log_file" + echo -e "\tversion: $(_get_distro_version)" | tee -a "$log_file" + directory_size=$(_get_dir_size "/") + echo -e "\troot: /" | tee -a "$log_file" + echo -e "\t\tsize: $directory_size" | tee -a "$log_file" + + directory_size=$(_get_dir_size "$INST_DIR") + echo -e "\tarchfx_dir: $INST_DIR" | tee -a "$log_file" + echo -e "\t\tsize: $directory_size" | tee -a "$log_file" + + echo -e "docker:" | tee -a "$log_file" + echo -e "\tlocation: $(_where_is_docker)" | tee -a "$log_file" + echo -e "\trunning: $(_is_docker_running)" | tee -a "$log_file" + echo -e "\tdata_root: $(_docker_root_dir)" | tee -a "$log_file" + + + echo -e "\tloki: $(_is_loki_plugin_installed)" | tee -a "$log_file" + + echo -e "outbound_connections:" | tee -a "$log_file" + declare -a urls=("https://www.google.com 200" + "https://arch.archfx.io/api/v1/server/ 200" + "https://portainer.overseer.archfx.io 200" + "https://portaineredge.overseer.archfx.io 404" + "https://ecr.archfx.io 401" + ) + for url_response in "${urls[@]}"; do + read -ra url_response <<< "$url_response" # turn url and response into an array + echo -e "\turl: ${url_response[0]}" | tee -a "$log_file" + echo -e "\t\tconnected: $(_outbound_connections ${url_response[@]})" | tee -a "$log_file" + done +} + + +####################################### +# Display latest report +####################################### +function latest_report() { + ls -t logs_* >/dev/null + if [ $? -eq 0 ]; then + file=$(ls -t logs_* | head -1) + echo ${PWD}/$file + cat $file + else + _warning_msg "Log files not yet created. Run:" + _success_msg "\n./broker_preflight.sh check" + fi +} + + +####################################### +# Command Line Arguments +####################################### +function usage () { + echo "ArchFX Broker preflight checklist" + echo "" + echo "Usage: $ME [options]" + echo "Options:" + echo " $ME check : Runs checks and generates report" + echo " $ME report : Displays last report" + echo " $ME help : Prints this usage" + echo "" +} + + +function do_arguments() { + if (( $# < 1 )); then + usage + exit 0 + fi + + local args="$@" + + + if [[ ${args} == 'check' ]]; then + preflight_checks + elif [[ ${args} == 'report' ]]; then + latest_report + elif [[ ${args} == 'help' ]]; then + usage + else + usage + _failure_msg "Error: Unknown Command: ${args}" + fi + exit 0 +} +####################################### +# Having this as the last line guarantees that the entire file has been read +do_arguments $@ diff --git a/src/tasks.py b/src/tasks.py index a256cb9..b993590 100644 --- a/src/tasks.py +++ b/src/tasks.py @@ -1,4 +1,5 @@ from invoke import task +import invoke import logging import docker import pyfiglet @@ -26,7 +27,6 @@ def _set_log_level(verbose=0) -> None: # Actually set the logging level logging.basicConfig(level=log_levels[verbose]) - ########################################### # Tasks @@ -72,41 +72,6 @@ def hello(c, name="world", verbose=0): logger.debug("Said hello.") -@task(incrementable=['verbose']) -def dockerinfo(c, verbose=0): - """Get Docker installation information - """ - - _set_log_level(verbose) - - logger.debug("Looking for Docker installation...") - - ####TODO: add try/except - client = docker.DockerClient(base_url='unix://var/run/docker.sock') - - info = client.info() - client.close() - - print(f"{'Árchetecture':<20}: {info.get('Architecture')}") - print(f"{'Containers':<20}: {info.get('Containers')}") - print(f"{'Containers Running':<20}: {info.get('ContainersRunning')}") - print(f"{'DockerRootDir':<20}: {info.get('DockerRootDir')}") - print(f"{'HttpProxy':<20}: {info.get('HttpProxy')}") - print(f"{'HttpsProxy':<20}: {info.get('HttpsProxy')}") - print(f"{'Images':<20}: {info.get('Images')}") - print(f"{'KernelVersion':<20}: {info.get('KernelVersion')}") - print(f"{'LoggingDriver':<20}: {info.get('LoggingDriver')}") - print(f"{'Name':<20}: {info.get('Name')}") - print(f"{'NoProxy':<20}: {info.get('NoProxy')}") - print(f"{'OSType':<20}: {info.get('OSType')}") - print(f"{'OperatingSystem':<20}: {info.get('OperatingSystem')}") - print(f"{'ServerVersion':<20}: {info.get('ServerVersion')}") - print(f"{'SystemTime':<20}: {info.get('SystemTime')}") - - from pprint import pprint - #pprint(client.df()) - - @task(incrementable=['verbose']) def netspeed(c, verbose=0): """Run an internet speedtest @@ -137,3 +102,90 @@ def netspeed(c, verbose=0): print(f"{'PING':<20}: {int(s.results.ping)}ms") print(f"{'UPLOAD':<20}: {int(s.results.upload / 1024 / 1024)}Mbps") print(f"{'DOWNLOAD':<20}: {int(s.results.download / 1024 / 1024)}Mbps") + + +@task(incrementable=['verbose']) +def dockerinfo(c, verbose=0): + """Get Docker installation information + """ + + _set_log_level(verbose) + + logger.debug("Looking for Docker installation...") + + try: + client = docker.from_env() + except Exception as e: + raise invoke.Exit("ERROR: Docker connection failed.", e) + info = client.info() + plugins = client.plugins.list() + client.close() + + print('-'*40) + print(f"{'System Name':<20}: {info.get('Name')}") + print(f"{'Árchetecture':<20}: {info.get('Architecture')}") + print(f"{'OSType':<20}: {info.get('OSType')}") + print(f"{'Kernel Version':<20}: {info.get('KernelVersion')}") + print(f"{'Operating System':<20}: {info.get('OperatingSystem')}") + print(f"{'System Time':<20}: {info.get('SystemTime')}") + + print('-'*40) + print(f"{'Docker Version':<20}: {info.get('ServerVersion')}") + print(f"{'Docker Root':<20}: {info.get('DockerRootDir')}") + print(f"{'Logging Driver':<20}: {info.get('LoggingDriver')}") + print(f"{'Images':<20}: {info.get('Images')}") + print(f"{'Containers':<20}: {info.get('Containers')}") + print(f"{'Containers Running':<20}: {info.get('ContainersRunning')}") + loki = next((x for x in plugins if x.name == 'loki:latest'), None) + if loki: + print(f"{'Loki':<20}: {loki.name}") + print(f"{' ':<20}: {'enabled' if loki.enabled else 'disabled'}") + for setting in loki.settings: + print(f"{' ':<20}: {setting}:{loki.settings.get(setting)}") + else: + print(f"{'Loki':<20}: {'Loki not found'}") + + print('-'*40) + print(f"{'HttpProxy':<20}: {info.get('HttpProxy')}") + print(f"{'HttpsProxy':<20}: {info.get('HttpsProxy')}") + print(f"{'NoProxy':<20}: {info.get('NoProxy')}") + print('-'*40) + + #from pprint import pprint + #pprint(ddf['Volumes']) + +####TODO: check outbound connections + print(f"{'verify correct time':<20}: {'TBD'}") +####TODO: add task to check remaining disk size on host system + print(f"{'Drive space':<20}: {'TBD'}") +####TODO: check outbound connections + print(f"{'Firewall':<20}: {'TBD'}") + #declare -a urls=("https://www.google.com 200" + # "https://arch.archfx.io/api/v1/server/ 200" + # "https://portainer.overseer.archfx.io 200" + # "https://portaineredge.overseer.archfx.io 404" + # "https://ecr.archfx.io 401" +####TODO: get docker-compose version + +@task(incrementable=['verbose']) +def dockertest(c, verbose=0): + """Test Docker installation + """ + + _set_log_level(verbose) + + logger.debug("Testing Docker installation...") + + try: + client = docker.from_env() + except Exception as e: + raise invoke.Exit("ERROR: Docker connection failed.", e) + info = client.info() + plugins = client.plugins.list() + # print(client.containers.run('netyeti/toolbox:latest', 'echo hello world')) + client.images.pull("netyeti/toolbox:latest") + + from pprint import pprint + pprint(client.swarm.attrs) + + client.close()