gns3 deploy initial repo

This commit is contained in:
2026-05-28 06:56:46 -07:00
commit d1ca7c6692
17 changed files with 4652 additions and 0 deletions
+142
View File
@@ -0,0 +1,142 @@
# TODO.md Convention Adoption
`[x]` done, `[-]` partial, `[ ]` not started
---
## Phase 1: Low-Hanging Fruit (done or nearly done)
- [x] `set -euo pipefail` + `IFS=$'\n\t'`
- [x] `readonly PATH` (Linux-only, homebrew paths removed)
- [x] Structured header block with metadata
- [x] `_READONLY_GLOBAL_` naming for constants
- [x] `_local_var` naming for function locals and iterators
- [x] `"${VAR}"` expansion everywhere (quoted + braced)
- [x] `log_*` hierarchy (`info`, `ok`, `warn`, `error`, `fatal`)
- [x] `log_warn_sticky`->`WARN_MESSAGES` array
- [x] `ensure_directory` / `ensure_config` / `require_file` helpers
- [x] `fetch_file` (stdout-based, composable)
- [x] `render_template` (stdin-based, `{{KEY}}` substitution)
- [x] `enable_and_start` with retry loop
- [x] Predicates: `file_exists`, `dir_exists`, `var_exists`, `port_open`
- [x] `if/then/fi` instead of `[[ ]] &&` shorthand (most converted)
- [x] `encrypted_copy` uses `openssl enc` with `-pbkdf2`
- [x] Decrypt commands match encryption params
- [x] `gns3_repo_present` handles deb822 format
- [x] Sudoers lines have no leading whitespace
- [x] Stray box-drawing chars removed from section headers
- [x] `fetch_resource` removed `fetch_file` used everywhere
- [x] IP lookups cached as `SERVER_PUBLIC_IP` / `SERVER_PRIVATE_IP` / `SERVER_HOSTNAME`
- [x] No redundant IP re-checks mid-script
- [x] `.shellcheckrc` with justified exclusions
- [-] Remaining `[[ ]] && / ||` patterns most converted, grep to find stragglers
---
## Phase 2: Structural Alignment
- [ ] Replace `on_error()` + separate `INT/TERM` trap with single `cleanup()` on `EXIT`
- Convention: `trap cleanup EXIT` as first line of `main()`
- `cleanup()` preserves exit code, disarms traps, `set +e`
- Restart GNS3 on failure (current `on_error` behavior) moves into cleanup
- INT/TERM: set context flag and `exit` - cleanup runs via EXIT trap
- [ ] Add `setup_tempdir()` - centralized `TEMP_DIR` used by `apt_retry` and `ensure_config`
- Currently both use ad-hoc `mktemp`
- `ensure_config` should use `mktemp "${TEMP_DIR}/..."` instead of `mktemp "${_path}.XXXXXX"`
- [ ] Add tracking arrays wired to helpers:
- `DIRECTORIES_CREATED``ensure_directory` appends
- `SERVICES_ENABLED``enable_and_start` appends
- `PACKAGES_INSTALLED``install_packages` populates (optional)
- Summary reads from these arrays
- [ ] Add `ROLLBACK_SERVICES` / `ROLLBACK_DIRS` typed registries
- `cleanup()` iterates in reverse on failure
- [ ] Replace `flock` lockfile with `mkdir`-based lock + stale PID detection (skeleton pattern)
- [ ] Remove `WARNINGS_OCCURRED` or use it - currently set but never read
- [ ] Add `require_args` to 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_SNAKE` for all placeholders (they're config values, not locals)
- [ ] Rename phase functions to convention verbs:
- `preflight_checks`->`preflight`
- `setup_config_server`->`config_server`
- `configure_firewall`->`firewall`
- `apply_sysctl_hardening`->`hardening`
- `start_services`->(merge into per-service phases or remove)
- `print_summary`->`summary`
- [ ] Rename sub-functions with phase prefix:
- `setup_groups`->`acct_create_groups`
- `setup_gns3_user`->`acct_create_gns3_user`
- `propagate_groups_to_invoker`->`acct_add_invoker`
- `add_gns3_repository`->`repo_add_gns3`
- `add_docker_repository`->`repo_add_docker`
- VPN functions: `ovpn_*` and `wg_*` prefixes
- [ ] Reorder function definitions to match execution order
- [ ] Add INDEX section to header mapping functions to sections
- [ ] Add `VERSION` constant, print in `--help` and summary
- [ ] Cache `_SCRIPT_DIR_` as readonly global (currently computed multiple times in `fetch_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_noun` naming
- [ ] Phase banner comments with purpose description
- [ ] Flag gating in `main()` with `if/then`:
```bash
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 from `main()` before bootstrap
---
## Phase 5: Multi-File Split (future, when script exceeds ~1000 LOC of logic)
- [ ] `conf/` - readonly vars/arrays per feature
- [ ] `lib/` source-only helpers, no `main()`
- [ ] `mod/` executable modules with numeric prefix ordering
- [ ] `bootstrap.sh` top-level orchestrator, executes `mod/*.sh`
- [ ] Source guards: `[[ -n "${_LIB_X_LOADED:-}" ]] && return 0`
- [ ] Direct-execution guards on sourced files
---
## Ongoing / Per-Commit
- [ ] `shfmt -i 2 -ci` before commit
- [ ] `shellcheck` zero warnings (with `.shellcheckrc` exclusions)
- [ ] 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_file` before modifying existing configs (not yet implemented)
---
## Known Deferred Items
- [ ] `check_integrity()` SHA256 validation for downloaded resources
- [ ] `--with-optimization` phase 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.list` still uses heredoc (inline `$(dpkg --print-architecture)` call)
- [ ] Validate function could check `ufw status numbered` rule count matches expectations
- [ ] Landing page: version-matched GNS3 client download URLs via JS
- [ ] GPG-signed bootstrap at `lrk.cx/gns3`
---