6.1 KiB
6.1 KiB
TODO.md Convention Adoption
[x] done, [-] partial, [ ] not started
Phase 1: Low-Hanging Fruit (done or nearly done)
set -euo pipefail+IFS=$'\n\t'readonly PATH(Linux-only, homebrew paths removed)- Structured header block with metadata
_READONLY_GLOBAL_naming for constants_local_varnaming for function locals and iterators"${VAR}"expansion everywhere (quoted + braced)log_*hierarchy (info,ok,warn,error,fatal)log_warn_sticky->WARN_MESSAGESarrayensure_directory/ensure_config/require_filehelpersfetch_file(stdout-based, composable)render_template(stdin-based,{{KEY}}substitution)enable_and_startwith retry loop- Predicates:
file_exists,dir_exists,var_exists,port_open if/then/fiinstead of[[ ]] &&shorthand (most converted)encrypted_copyusesopenssl encwith-pbkdf2- Decrypt commands match encryption params
gns3_repo_presenthandles deb822 format- Sudoers lines have no leading whitespace
- Stray box-drawing chars removed from section headers
fetch_resourceremovedfetch_fileused everywhere- IP lookups cached as
SERVER_PUBLIC_IP/SERVER_PRIVATE_IP/SERVER_HOSTNAME - No redundant IP re-checks mid-script
.shellcheckrcwith justified exclusions- [-] Remaining
[[ ]] && / ||patterns most converted, grep to find stragglers
Phase 2: Structural Alignment
- Replace
on_error()+ separateINT/TERMtrap with singlecleanup()onEXIT- Convention:
trap cleanup EXITas first line ofmain() cleanup()preserves exit code, disarms traps,set +e- Restart GNS3 on failure (current
on_errorbehavior) moves into cleanup - INT/TERM: set context flag and
exit- cleanup runs via EXIT trap
- Convention:
- Add
setup_tempdir()- centralizedTEMP_DIRused byapt_retryandensure_config- Currently both use ad-hoc
mktemp ensure_configshould usemktemp "${TEMP_DIR}/..."instead ofmktemp "${_path}.XXXXXX"
- Currently both use ad-hoc
- Add tracking arrays wired to helpers:
DIRECTORIES_CREATED←ensure_directoryappendsSERVICES_ENABLED←enable_and_startappendsPACKAGES_INSTALLED←install_packagespopulates (optional)- Summary reads from these arrays
- Add
ROLLBACK_SERVICES/ROLLBACK_DIRStyped registriescleanup()iterates in reverse on failure
- Replace
flocklockfile withmkdir-based lock + stale PID detection (skeleton pattern) - Remove
WARNINGS_OCCURREDor use it - currently set but never read - Add
require_argsto helper functions (from skeleton)
Phase 3: Naming & Organization
- Standardize template placeholder names
- Current: mixed
_DEPLOY_MARKER_/_listen_host/GNS3_PORT/_hw_accel - Target: consistent
SCREAMING_SNAKEfor all placeholders (they're config values, not locals)
- Current: mixed
- Rename phase functions to convention verbs:
preflight_checks->preflightsetup_config_server->config_serverconfigure_firewall->firewallapply_sysctl_hardening->hardeningstart_services->(merge into per-service phases or remove)print_summary->summary
- Rename sub-functions with phase prefix:
setup_groups->acct_create_groupssetup_gns3_user->acct_create_gns3_userpropagate_groups_to_invoker->acct_add_invokeradd_gns3_repository->repo_add_gns3add_docker_repository->repo_add_docker- VPN functions:
ovpn_*andwg_*prefixes
- Reorder function definitions to match execution order
- Add INDEX section to header mapping functions to sections
- Add
VERSIONconstant, print in--helpand summary - Cache
_SCRIPT_DIR_as readonly global (currently computed multiple times infetch_file)
Phase 4: Macro Refactor
- Two-tier
main()structure:main->bootstrap->preflight->repositories->packages → accounts->gns3->docker->openvpn->wireguard → welcome->firewall->hardening->config_server → validate->summary - Each phase is a noun function containing only sub-function calls
- Sub-functions use
phase_verb_nounnaming - Phase banner comments with purpose description
- Flag gating in
main()withif/then:if [[ "${WITH_DOCKER}" -eq 1 ]]; then docker; fi if [[ "${WITH_OPENVPN}" -eq 1 ]]; then openvpn; fi - Add predicate functions for recurring checks:
service_active/user_exists/interface_up/repo_present/packages_installed
- Move
apply_option_flags(rollup) into its own named phase or call frommain()before bootstrap
Phase 5: Multi-File Split (future, when script exceeds ~1000 LOC of logic)
conf/- readonly vars/arrays per featurelib/source-only helpers, nomain()mod/executable modules with numeric prefix orderingbootstrap.shtop-level orchestrator, executesmod/*.sh- Source guards:
[[ -n "${_LIB_X_LOADED:-}" ]] && return 0 - Direct-execution guards on sourced files
Ongoing / Per-Commit
shfmt -i 2 -cibefore commitshellcheckzero warnings (with.shellcheckrcexclusions)- Update
Changed:date in header on substantive edits - Update INDEX when function structure changes
- Convention: Check / Do / Verify for every action
- Convention: secrets never as function arguments; use env/files/stdin
- Convention:
backup_filebefore modifying existing configs (not yet implemented)
Known Deferred Items
check_integrity()SHA256 validation for downloaded resources--with-optimizationphase TCP/KVM tuning (BBR, swappiness, etc.)- 26.04 codename fallback check GNS3 PPA Packages.xz for actual content
- OpenVPN client.ovpn still uses heredoc (PEM blocks don't work with
render_template) docker.liststill uses heredoc (inline$(dpkg --print-architecture)call)- Validate function could check
ufw status numberedrule count matches expectations - Landing page: version-matched GNS3 client download URLs via JS
- GPG-signed bootstrap at
lrk.cx/gns3